JWT는 웹 표준 (RFC 7519) 으로, 정보의 안정성 있는 전달을 목표로 한다.
따라서 다양한 개발언어에서 지원되고 있다.
JWT는 또한 자가 수용적이다.
자가 수용적이란 자신 스스로 모든 정보를 가지고있다는 의미이다. 토큰에 대한 정보, 전달할 정보, 검증 signature까지 모두 가지고 있다.
JWT는 .으로 구분되는 머리 가슴 배 Header, Payload, Signature로 구성되어있다. 아래의 예시는 jwt.io에서 제공하는 예시중 하나이다.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
첫번째 부분이 Header 부분이다.
헤더에는 두가지 정보가들어있다.
type: 토큰의 타입 (JWT)
alg: 해싱 알고리즘, 즉 서명이 무슨 알고리즘으로 되어있는지에 대한 정보이다.
예시의 헤더는 다음과 같은 정보를 담고있다.
{
"alg": "HS256",
"typ": "JWT"
}
JWT타입의 토큰을 HS256으로 암호화했다는 의미이다.
HS256은 HMAC SHA256 방식이다.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
페이로드 부분에는 토큰에 담을 정보가 들어간다. 여기에 담기는 정보 하나를 클레임이라 하고 클레임은 name : value 구조를 가진다.
이 클레임은 총 3가지 종류가 있다.
iss: 토큰 발급자 (issuer)
sub: 토큰 제목 (subject)
aud: 토큰 대상자 (audience)
exp: 토큰의 만료시간 (expiraton), 시간은 NumericDate 형식으로 되어있어야 하며 (예: 1480849147370) 언제나 현재 시간보다 이후로 설정되어있어야합니다.
nbf: Not Before 를 의미하며, 토큰의 활성 날짜와 비슷한 개념입니다. 여기에도 NumericDate 형식으로 날짜를 지정하며, 이 날짜가 지나기 전까지는 토큰이 처리되지 않습니다.
iat: 토큰이 발급된 시간 (issued at), 이 값을 사용하여 토큰의 age 가 얼마나 되었는지 판단 할 수 있습니다.
jti: JWT의 고유 식별자로서, 주로 중복적인 처리를 방지하기 위하여 사용됩니다. 일회용 토큰에 사용하면 유용합니다.
출처 ㅣ https://velopert.com/2389
예시로 주어진 JWT에서는 등록클레임, 비공개 클레임을 사용하며 다음과 같다.
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
제목, 이름, 그리고 발급시간을 가지고 있다. 로그인 환경에서는 여기에 exp를 넣는다.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
서명은 해당 토큰의 인정여부를 검증하기 위한 장치이다. 헤더의 인코딩값과 페이로드의 인코딩값을 합하고 서버의 비밀키로 해쉬하여 생성한다.
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
your-256-bit-secret
)
이렇게 만들어진 해쉬를 미리 정해진 알고리즘으로 인코딩하면 그 값이 서명이 된다.
서버에서는 검증을 할 때 이 부분을 미리 저장된 시크릿과 알고리즘으로 뜯어서 확인해보고 검증하는 것이다.
예시에서는 'your-256-bit-secret' 이라는 비밀키로 암호화 서명을 하였다.
OsYeNeIRzSGp0Ss232RIL9xjKwsmo-c6slPSi0plpWE
시크릿을 Secret로 바꾸면 이렇게 변하게 된다.
이로써 JWT의 개념설명은 끝이다.
이를 활용하는 로그인에 대해 정리하면, 프로젝트에서 가장 골머리를 썩게 만들었던 로그인 부분에 대한 모든 정리가 끝난다.