JWT는 토큰 기반 인증 방식에서 주로 사용되는 토큰입니다. 주로 로그인 된 특정 사용자를 인증하기 위해서 사용됩니다. REST API 서버의 확장성을 높이는 데 JWT 인증 방식이 한 몫을 하고 있습니다. 이번 글에서는 JWT 구조에 대해 알아보겠습니다.
JWT란?
JWT는 Json Web Token의 약자입니다.
당사자들이 서로 Json 데이터를 안전하게 주고 받기 위해 고안된 표준입니다.
JWT 구조
JWT가 어떻게 생겼는지 봅시다.
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJncmVlbm5ldXJvbkBlbWFpbC5jb20iLCJyb2xlIjoiUk9MRV9VU0VSIiwiaWF0IjoxNjc0ODg3NzM4LCJleHAiOjE2NzQ5NzQxMzh9.4koOlEtPTTObnMPk5xF3l2zuXRNnlkqYNg1eni8yit0
JWT 구조를 자세히 보면 “.” 을 구분자로 세 개의 파트로 나뉘어져 있는 것을 알 수 있습니다. 각 파트는 아래와 같이 각각 다른 이름과 역할을 가집니다.
Header.Payload.Signature
JWT의 각 파트는 base64Url 인코딩 되어 있습니다.
아래의 웹 페이지에서 누구나 토큰을 쉽게 디코딩 해볼 수 있습니다.
헤더 (Header)
토큰의 타입과 사이닝 알고리즘에 대한 정보가 담겨있는 파트입니다.
Header | base64Url 디코딩 결과 |
---|---|
eyJhbGciOiJIUzI1NiJ9 | {"alg":"HS256"} |
- typ : 토큰의 타입
- alg : 서명 알고리즘 (the signing algorithm being used)
페이로드 (Payload)
어떤 상태 값이나 추가적인 정보가 담겨 있는 파트입니다. 권장하는 내용으로 미리 정의되어 있는 key-value를 담거나(https://www.rfc-editor.org/rfc/rfc7519#section-4.1), 개발자가 임의로 key-value를 정의하여 담을 수 있습니다. header, payload에 담긴 key-value들을 클레임(claim) 이라고 합니다.
Payload | base64Url 디코딩 결과 |
---|---|
eyJzdWIiOiJncmVlbm5ldXJvbkBlbWFpbC5jb20iLCJyb2xlIjoiUk9MRV9VU0VSIiwiaWF0IjoxNjc0ODg3NzM4LCJleHAiOjE2NzQ5NzQxMzh9 | {"sub":"greenneuron@email.com","role":"ROLE_USER","iat":1674887738,"exp":1674974138} |
- sub : 토큰 발행 시 지정된 JWT의 주체 (Principal)
- iat : 토큰 발행 일시
- exp : 토큰 만료 일시
- role : 개발자가 임의로 추가한 claim
시그니처 (Signature)
Header에 명시된 서명 알고리즘으로 아래의 표와 같이 서명했을 때 생성된 Signature가 담겨있는 파트입니다. 서명에는 인코딩된 헤더, 인코딩된 페이로드와 Secret(토큰 발행 시 사용한 비밀키)가 필요합니다. 서명 시 생성된 문자열이 Signature와 동일한지 확인함으로써, 토큰 발행자는 전달 받은 토큰이 자신이 발행한 토큰이 맞는지, 변조되지 않은 유효한 토큰인지 검증할 수 있습니다.
Signature | 서명 방법 (Secret : greenneuron) |
---|---|
4koOlEtPTTObnMPk5xF3l2zuXRNnlkqYNg1eni8yit0 | HMACSHA256( base64UrlEncode(header) +"."+ base64UrlEncode(payload), "s6v8y/B?E(H+MbQeThWmZq4t7w!z$C&F" ) |
참고 자료
- JWT 공식 소개 문서
: https://jwt.io/introduction
좋은 내용 감사합니다.
Header, Payload에서 사용하는 Base64 인코딩은, 일반적인 Base64가 아니라, URL에서 사용할 수 있는 문자들만 사용하는 Base64URL 인코딩 방식인 것 같은데, Signature도 마찬가지로 URL에서 사용 가능한 문자만 포함되는 건가요?
안녕하세요! 좋은 질문 감사합니다. RFC7519의 내용을 자세히 보니 다음과 같은 문장이 있었습니다.
“A JWT is represented as a sequence of URL-safe parts separated by period (‘.’) characters. Each part contains a base64url-encoded value.”
위 내용으로 보아 Signature 파트도 base64url 인코딩이 적용되어야 한다고 생각됩니다. 질문 주신 내용을 반영해서 글을 조금 수정하였습니다. 감사합니다👍