개발
home
🔑

Json Web Token(JWT) 빠르게 정리

Created
2022/05/21
Tags
JWT
2022-05-21 @이영훈
인증 쪽에서 최근에 많이 사용되고 있는 JWT를 기록으로 남깁니다

JWT 구성

JWT는 Header.Payload.Signature로 구성되어 있습니다
각 요소들을 자세히 살펴보겠습니다
1.
Header는 아래와 같이 구성되어 있습니다
{ "alg": "HS256", "typ": "JWT" }
JSON
복사
해시 알고리즘과 JWT라는 타입을 명시하고 있습니다
2.
Payload는 메시지 본문의 역할입니다. JWT 토큰에 저장하고 싶은 값을 넣는 공간입니다
{ "sub": "1234567890", "name": "John Doe", "iat": 1516239022, "exp": 1516249022 }
JSON
복사
유저의 id, email, name(nickname) 등 유저에 대한 정보를 기입합니다
그리고 iat은 토큰이 발급된 시간, exp는 토큰이 만료되는 시간입니다
이 시간들을 unix timestamp 시간입니다 unix timestamp는 1970년 1월 1일 00:00 UTC 기준으로 시간이 지난 "초"를 나타냅니다
3.
마지막으로 Signature 부분입니다
Signature는 토큰이 위변조 되었는 지 확인하는 부분입니다
base64 encoded된 header와 pyaload를 Header.alg에 기입된 해시 알고리즘으로 해시한 값입니다
서버에서는 JWT 인증 요청이 들어오면 우선 Signature를 확인하고 위변조가 되었으면 MalformedException과 같은 에러 메시지를 반환합니다

JWT 실습으로 만들어보기

백문이 불여일견 JWT를 만들어보면서 빠르게 이해해보도록 하겠습니다
jwt.io에 있는 다음의 JWT가 어떻게 만들어지는 지 알아보겠습니다
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
1.
Header 부분을 만들어보겠습니다
헤더의 값은 아래와 같습니다
{ "alg": "HS256", "typ": "JWT" }
JSON
복사
json을 minify 하고 base64로 인코딩을 합니다
// 1. minify json {"alg":"HS256","typ":"JWT"} // 2. encode base64 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
JSON
복사
그러면 JWT에 있는 header와 동일한 값이 만들어졌습니다
2.
다음으로 Payload 입니다
Payload 만드는 방법도 Header와 동일합니다
Payload의 값은 아래와 같습니다
{ "sub": "1234567890", "name": "John Doe", "iat": 1516239022 }
JSON
복사
마찬가지로 minify json을 한 뒤에 base64로 인코딩을 합니다
// 1. minify json {"sub":"1234567890","name":"John Doe","iat":1516239022} // 2. base64 encode eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ== // 3. deal with url unsafe characters eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
JSON
복사
여기에서 유의해야할 점은 url-safe 하지 않은 문자열을 처리해야하는 점입니다
=은 삭제합니다
/는 _로 치환합니다
url unsafe 문자열까지 처리하고 나면 JWT의 payload와 동일한 문자열이 만들어졌습니다
3.
마지막으로 Signataure 부분입니다
psuedo code는 다음과 같습니다
SHA256AsHex( base64Encode(minifyJson(header)) + '.' + base64Encode(minifyJson(payload), 'your jwt secret' )
JavaScript
복사
비밀번호는 jwt.io에 나와있는 것과 동일하게 your-256-bit-secret 으로 하겠습니다
SHA256AsHex( eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ, 'your-256-bit-secret' )
JavaScript
복사
HMAC (Hash-based Message Authentication Code)-SHA256 온라인 생성 사이트에서 위의 값과 비밀번호를 넣어서 생성해보겠습니다
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV/adQssw5c= 값을 얻었습니다
여기에서 url-unsafe한 문자열을 처리하겠습니다 (=는 삭제하고 /는 _로 치환)
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
JavaScript
복사
JWT signature와 동일한 값을 얻을 수 있습니다

마치며

JWT를 깊게 이해하기 위해서 다음과 같은 글을 함께 읽어보면 좋습니다
시간 효율성을 위해서 큰 흐름을 한국어 블로그로 잡고 영어 블로그, IETF 문서 순으로 공부하시는 것을 추천드립니다
그리고 JWT를 공부하실 때 기존에 많이 사용하던 Session을 이용한 인증 방식에 대해서도 공부해시는 것을 권장합니다 (여러 인증 서버가 있을 때 어떻게 인증을 처리하는 지 등 내부를 이해할 수 있어 좋습니다)