JWT를 읽기 전 Access Token에 대해서 먼저 알아야 한다. 그래야 JWT의 목적을 이해하기 쉽기 때문이다.
JWT?
access token은 유저가 로그인 성공 후 매번 로그인하지 않도록 하는 것으로 JWT는 이 access token을 생성하는 방법 중 하나이다. JWT안에는 유저 정보가 담겨져 있는 JSON 형태의 웹토큰으로, 암호화해서 클라이언트와 서버간에 주고받는다.
JWT 구조
아래와 같이 각각의 데이터를 인코딩 후 .
을 이용해 합친다.
1, 2번째 부분인 Header와 Payload는 인코딩하고, Signature는 암호화시킨 후 .
을 이용해 합친다. 1, 2번째 부분은 누구나 디코드할 수 있으나 3번째는 암호화시킨 사람만 복구화가 가능하다. 때문에 1, 2번째는 민감한 정보를 넣어서는 안된다.
Header . Payload . Signature
JWT 토큰 예시
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MjJ9.u8jurmtF3vo3HOPy4l3eXiDAr0PhtWjHhxUY6oF0vrI
header는 토큰의 타입과 해시 암호화 알고리즘으로 구성되어 있다.
- typ : 토큰의 타입, JWT만 존재
- alg : 해싱 알고리즘. (HMAC SHA256 or RSA). 헤더를 암호화 하는게 아니다. 토큰 검증시 사용.
{
"alg" : "HS256",
"typ" : "JWT"
}
Payload 정보
Payload는 user_id, expire, scope 등 실제 토큰으로 사용하려는 데이터가 담기는 부분이다. 각 데이터를 claim이라고 하며, 이는 name/value 한 쌍으로 이루어져 있고, 다음과 같이 3종류가 있다.
Registered Claims 등록된 클레임
서비스에서 필요한 정보들이 아닌, 토큰에 대한 정보들을 담기위하여 이름이 이미 정해진 클레임
- 등록된 클레임의 사용은 모두 선택적 (optional)이다.
- 필수는 아니지만 사용하길 권장하며 key는 모두 3자리 string이다.
- iss : 토큰 발행자 정보(issuer)
- sub : 제목(subject)
- exp : 만료일(expiration time), 시간은 NumericDate 형식으로 되어있어야 하며 (예: 1480849147370) 언제나 현재 시간보다 이후로 설정되어 있어야한다.
- aud : 토큰 대상자(audience)
- nbf : 토큰의 활성 날짜와 비슷한 개념(Not Before), NumericDate 형식으로 날짜를 지정하며, 이 날짜가 지나기 전까지는 토큰이 처리되지 않는다.
- iat : 토큰이 발급된 시간(issued at), 이 값을 사용하여 토큰의 age가 얼마나 되었는지 판단할 수 있다.
- jti : JWT의 고유식별자로서, 주로 중복적인 처리를 방지하기 위하여 사용된다. 일회용 토큰에 사용하면 유용하다.
Public Claims 공개 클레임
- 사용자 정의 claim
- 공개용 정보, 충돌방지를 위해 URI 포맷을 이용해 저장한다.
Private Claims 비공개 클레임
- 사용자 정의 claim
- 일반 정보를 저장한다. ex) user_id
payload 예시
{
"iss": "test.com",
"exp": "1485270000000",
"https://test.com/jwt_claims/is_admin": true,
"userId": "foo5",
"username": "홍길동"
}
Signature 서명
- header와 payload의 데이터 무결성과 변조 방지를 위한 서명부분이다.
- secret key를 포함하여 암호화 되어있다.
- 서명은 위에서 만든 헤더(Header)와 페이로드(Payload)의 값을 각각 BASE64로 인코딩하고, 인코딩한 값을 비밀 키를 이용해 헤더(Header)에서 정의한 알고리즘으로 해싱을 하고, 이 값을 다시 BASE64로 인코딩하여 생성한다.
JWT의 장점
- 사용자 인증에 필요한 모든 정보는 토큰 자체에 포함하기 때문에 별도의 인증 저장소가 필요없다.
- 쿠키를 전달하지 않아도 되므로 쿠키를 사용함으로써 발생하는 취약점이 사라진다.
- URL 파라미터와 헤더로 사용
- 트래픽 대한 부담이 낮음
- REST 서비스로 제공 가능
- 내장된 만료
- 독립적인 JWT
JWT의 단점
- payload 인코딩 : 토큰의 Payload부분이 암호화가 되어 있는 것이 아니라 인코딩만 되어있기 때문에 중간에 Payload를 탈취하면 디코딩을 통해 데이터를 볼 수 있다. 그러므로 JWE를 통해 암호화하거나 Payload에 중요 데이터를 넣지 않아야한다.
- 토큰 길이 : Payload에 claim set을 저장하기 때문에 정보가 많아질수록 토큰의 길이가 늘어나 네트워크에 부하를 줄 수 있다.
- 토큰은 한번 만들면 서버에서 제어가 불가능하여 토큰을 임의로 삭제할 수 있는 방법이 없기 때문에 토큰 만료시간을 꼭 넣어주는 것이 좋다.
- 토큰은 클라이언트 side에서 관리해야하기 때문에 토큰을 저장해야한다.
- 토큰 자체에 정보를 담고 있으므로 양날의 검이 될 수 있다.
참고 사이트
https://sanghaklee.tistory.com/47