일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
- sonarqube
- DP
- 카카오클라우드
- 구름
- s3
- 카카오엔터프라이즈
- jsonwebtoken
- 백엔드 개발
- db
- objectstorage
- 함수 종속성
- java
- softeer
- 정렬
- 코드트리
- 완전탐색
- bfs
- bitmask
- 인가인증
- MESSAGEBROKER
- On-Premise
- es_java_home
- 동전 퍼즐
- dockercompose
- 소프티어
- BFS
- DFS
- 자바
- 알고리즘
- CODETREE
- Today
- Total
wooing
JWT와 사용 전략 본문
JWT란?
JSON 웹 토큰
(JSON Web Token, JWT, "jot”)은 선택적 서명 및 선택적 암호화를 사용하여 데이터를 만들기 위한 인터넷 표준으로, 페이로드는 몇몇 클레임(claim) 표명(assert)을 처리하는 JSON 을 보관하고 있다. 토큰은 비공개 시크릿 키 또는 공개/비공개 키를 사용하여 서명된다.
- 위키백과
JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object.
JSON은 당사자간의 정보를 안전하게 전송하기 위한 컴팩트하고 독립적인 방식을 정의하는 개방형 표준(RFC 7519)이다.
- jwt.io
한마디로 정리하자면 JSON을 암호화한 웹 토큰이고, 인증/인가에 사용하는 표준이다.
웹 토큰이 뭔데?
웹 토큰은 웹 애플리케이션에서 사용자 인증 및 정보 교환을 위한 방식이다.
과거에 버스를 탈때는 토큰판매점에서 현금으로 토큰을 구매하고, 버스 탑승시에 토큰을 지불하는 방법이었다고 한다. 버스 토큰이 도입된 이유로 버스에서 현금 거래가 이뤄지는 과정에서 중간에 현금을 가로채는 일이 빈번했기때문에 이를 관리하기 위한 수단으로 등장했다고 한다.
버스 토큰의 개념과 등장배경이 웹 토큰의 개념과 등장배경 같다고 볼 수 있다. 현금과 같은 중요한 데이터들이 오갈때 이를 보호하기 위한 본인 확인 수단이 필요했고, 그 수단으로 웹 토큰을 사용하는것이다.
토큰에 사용자의 인증 정보를 담아 서버에 보내면 서버는 해당 정보가 유효한지 확인(인증)하고, 데이터에 접근할 수 있는 권한을 준다(인가).
JWT구조
Json은 아래의 세가지 구조로 나누어져있고 각각 . 으로 구분한다.
- Header
- Payload
- Signature
Header
토큰에 대한 기본 정보가 담겨있다. 암호화하는 알고리즘과 토큰의 타입을 저장한다. 알고리즘의 종류는
HS256, HS384, HS512, ES257, ES384, ES512, RS256, RS384, RS512, PS256, PS384, PS512가 있다.
{
"alg": "HS256",
"typ": "JWT"
}
Payload
Claim을 포함하는 부분이다. Claim이란 토큰의 추가적인 데이터를 말한다. 일반적으로 이 부분에 사용자에 대한 정보를 담는다.
Claim 종류
Registerd(등록된) claims
토큰에 대한 기본 정보를 담기 위한 클레임으로 생성시 정해진 클레임이다. 해당 claim정보들은 선택적으로 사용 가능하다.
iss(발급자), exp(만료기간), sub(토큰 제목), aud(토큰 대상자) 등...
Public(공개) Claims
자유롭게 정의할 수 있는 claim으로 충돌을 피하기 위해 여기에 정의된 이름으로 사용하거나 충돌 방지 네임스페이스를 포함하는 URI형식으로 지정해야한다.
Private(비밀) Claims
이는 당사자간 (서버 - 클라이언트) 정보를 공유하기 위해 작성된 부분이다. 통신을 주고받는 당사자끼리 협의하여 자유롭게 키와 값을 정의하여 사용한다.
Signature
인코딩된 헤더, 인코딩된 페이로드, 비밀, 헤더에 지정된 알고리즘을 한번 더 암호화 하여 저장한 부분이다.
메세지가 전송 도중 변경되지 않았는지 확인하는데 사용한다.
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
위의 구성으로 아래와 같은 값을 만들어내어 웹 토큰으로써 사용한다.
JWT사용 방법
위에서 JWT를 웹 토큰으로 사용한다고 했다. 웹 토큰으로 사용하려면 HTTP요청에 토큰을 담아 함께 전송해야하는데 그 방법과 JWT사용 과정은 아래와 같다.
헤더에 토큰 담기
아래처럼 HTTP요청의 헤더에 Bearer 스키마를 사용하여 보낸다.
Bearer을 사용하는 이유는 OAuth 2.0인증 프레임워크에서 사용하는 방식이기 때문이라고 한다.
Authorization: Bearer <token>
서버에 인증 요청 보내기
- 클라이언트는 인증 서버에 로그인 요청을 한다.
- 인증 서버는 클라이언트의 로그인 정보를 식별하고 엑세스토큰과 리프레시 토큰을 발급하고, 토큰을 클라이언트에게 전달한다.
- 클라이언트는 발급받은 토큰을 헤더에 담아 요청에 사용한다.
액세스토큰? 리프레시토큰?
위의 사용방법에서 액세스토큰과 리프레시토큰이라는 단어가 등장했다. JWT가 토큰인거는 알겠는데 액세스토큰과 리프레시토큰은 생소할것이다. 액세스토큰은 인증과정에서 직접적인 검증을 통해 권한을 확인하고 인가를 받는 과정에 사용되는 토큰이고, 리프레시토큰은 액세스토큰이 만료되었을때 이를 검증하여 액세스토큰을 재발급하는 역할을 한다.
등장하게 된 배경으로는 액세스토큰이 긴 만료시간을 가진다면 탈취당했을때 긴 유효시간동안 악의적으로 사용될 수 있다. 이 문제를 방지하기 위해 엑세스토큰의 유효기간을 짧게 설정하고, 상대적으로 긴 리프레시토큰을 통해 재발급을 하여 사용자는 리프레시토큰 기간동안 인증 상태를 유지할 수 있도록 하였다.
토큰 재발급
앞서 설명했듯 액세스토큰의 유효기간을 짧게 설정하기때문에 토큰 재발급 과정은 필수적인 요소가 될 것이다. 일반적인 액세스토큰 재발급 과정은 아래와 같다.
Refresh Token Rotation(RTR)
하지만 위의 과정에서도 취약점은 존재한다. 만약 Refresh Token이 탈취당했다면 공격자는 해당 토큰으로 얼마든지 Access Token을 재발급 받을 수 있다는 문제가 있다. 이를 방지하기 위한 정책으로 Refresh Token Rotation(RTR) 이 있다.
RTR은 Access Token이 만료되어 Refresh Token으로 재발급 할때 Refresh Token도 재발급하여 새로운 한 쌍의 토큰으로 발급하는 것 이다.
그럼에도 한 쌍의 토큰이 모두 탈취되었다면 여전히 문제는 존재한다. 이 경우 Access Token을 최대한 짧게 유지하여 다시 Refresh Token으로 재발급 하도록 하고, 사용한 Refresh Token을 블랙리스트로 관리하여 탈취된 토큰의 사용을 방지할 수 있다.
JWT와 Redis
토큰 블랙리스트를 관리에 Redis를 많이 사용한다. 사실 DB의 역할만 할 수 있다면 어디에든 저장이 가능하다. 그럼에도 Redis를 많이 사용하는 이유는 다음과 같다.
Redis의 특징
Redis는 In memory NoSQL DB이다. In Memory이기때문에 성능적으로 매우 빠르며, TTL(Time To Live)를 지정하여 원하는 기간동안 데이터를 저장할 수 있다. 그리고 Redis의 데이터 저장방식인 Key value 형식도 하나의 특징이다.
위의 특징을 고려한다면, Refresh Token의 만료시간 관리, 블랙리스트 관리 등에 Redis를 사용하는것이 적합하다.
그렇다면 세션과 뭐가 다른거지?
세션에 대해 간단하게 설명하면, 클라이언트의 요청을 하나의 상태로 하여 서버에서 상태를 관리하고, 유지하는 방법으로 인가인증을 하는것을 말한다. 여기서 세션의 특징으로는 서버에서 상태를 관리하고 DB에 이를 저장하여 관리한다는점이 있는데 그렇다면 JWT와 Redis를 사용했을때 다른점이 무엇이 있는가라는 의문이 들 수 있다.
JWT를 사용하는 이유중 하나는 토큰 자체가 인증정보를 담고있어 서버에서 인증정보를 저장하지 않고 인증이 가능하다는 점(Stateless)이 있다. Redis에 저장하지 않아도 인증 과정에는 문제가 없고, 오직 보안을 위해 redis를 사용하는것이다. 그러나 세션은 인증을 위해 "무조건"DB에 인증정보를 저장해야한다. 여기서 차이점이 발생한다고 생각한다. 세션의 경우 모든 유저의 인증 정보를 저장하고, 인증과정에 사용되니 사용자가 많아질수록 부하가 심해지지만, JWT와 Redis를 사용할때는 리프레시토큰으로 재발급 할때나 로그아웃할때 블랙리스트로만 관리하면 되기때문에 DB조회의 빈도에서 차이가 발생한다.
이런 이유로 JWT + Redis 와 Sessio간에는 차이가 존재한다고 설명할 수 있다. 요약하자면, JWT + Redis는 여전히 Stateless하다는점, 그러나 Session방식은 Stateful하기때문에 모든 인증과정에 DB조회가 필요하다는점이다.
References
https://ko.wikipedia.org/wiki/JSON_%EC%9B%B9_%ED%86%A0%ED%81%B0
https://docs.tosspayments.com/resources/glossary/bearer-auth
https://velog.io/@chchaeun/%EC%9D%B8%EC%A6%9D%EA%B3%BC
https://www.reddit.com/r/golang/comments/nhvmfw/whats_the_difference_between_jwtwith_redis_vs/
https://stackoverflow.com/questions/43452896/authentication-jwt-usage-vs-session
'CS' 카테고리의 다른 글
정규화와 반정규화(비정규화)란? (1) | 2025.03.17 |
---|---|
OSI 7계층과 계층별 역할 (1) | 2025.01.19 |
[자료구조] AVL트리 [JAVA] (0) | 2020.08.30 |
[자료구조] 트리 (0) | 2020.07.20 |
[자료구조] 이진탐색트리, 바이너리서치트리(Binary Search Tree)[JAVA] (0) | 2020.07.19 |