JWT 는 JSON Web Token 의 약자로, 서버 API 를 호출할 때 토큰으로 주로 사용된다. JWT 는 크게 Header, Payload, Signature 라 불리는 세 개의 부분으로 나눌 수 있다. Header 에는 인코딩 알고리즘과 토큰의 타입을 정의하는 내용을 담고 있고, Payload 는 JWT 에 넣고 싶은 데이터를 가진다. 마지막으로, Signature 는 Header 와 Payload 의 내용을 검증할 때 사용한다. JWT 문자열을 생성하는 것은 jwt.io 홈페이지에서 해볼 수 있다.
이제 본 글의 목적에 맞게 JWT 문자열을 디코딩하여, 인코딩 했을 때의 JSON 값들을 추출하는 코드를 구현해보자.
우선, 디코딩을 하고자 하는 JWT 값을 선정한다. 본 글에서는 jwt.io 페이지에서 바로 나오는 값으로 진행한다.
위 사진에서 왼쪽에 인코딩된 값을 가져와서, Kotlin 변수로 저장한다.
val token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
JWT 값을 보면, "." 가 2개있고, jwt.io 페이지에선 "." 을 기준으로 색깔이 다르게 3 부분이 나뉘어져있는 것처럼 표현되어있다.
즉, 앞에 빨간색 글씨는 JWT 의 "Header" 부분을 인코딩 한 것이고, 중간에 보라색 글씨는 JWT 의 "Payload", 마지막에 하늘색 글씨는 "Signature" 를 인코딩한 것이다. 따라서, "." 을 기준으로 인코딩된 JWT 문자열을 나눠준다.
val token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MTcsIm5hbWUiOiJkZXYiLCJuaWNrbmFtZSI6ImRldiIsImlhdCI6MTY2Mzg0MzU2NiwiZXhwIjoxNjk1Mzc5NTY2fQ.nYxtyGoOgnjVPiGkMv9xNqcQuMO5aZ6ahzBBVqgzvOc"
val tokenParts = token.split(".")
tokenParts[0] 는 인코딩된 Header, tokenParts[1] 은 인코딩된 Payload, tokenParts[2] 는 인코딩된 Signature 가 된다. 이제 3개의 tokenParts 를 디코딩 해보자. 디코딩 할 때는 Base64 의 UrlDecoder 를 사용한다.
val token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MTcsIm5hbWUiOiJkZXYiLCJuaWNrbmFtZSI6ImRldiIsImlhdCI6MTY2Mzg0MzU2NiwiZXhwIjoxNjk1Mzc5NTY2fQ.nYxtyGoOgnjVPiGkMv9xNqcQuMO5aZ6ahzBBVqgzvOc"
val tokenParts = token.split(".")
print(tokenParts[0])
print(tokenParts[1])
print(tokenParts[2])
val decoder = Base64.getUrlDecoder()
val header = String(decoder.decode(tokenParts[0]))
val payload = String(decoder.decode(tokenParts[1]))
val signature = String(decoder.decode(tokenParts[2]))
print("header: $header")
print("payload: $payload")
print("signature: $signature")
Signature 는 원하는 모습으로 디코딩 되지 않았지만, Header 와 Payload 는 인코딩 당시에 넣었던 값 그대로 출력되는 것을 확인할 수 있다.
이처럼, JWT 문자열을 Base64 의 UrlDecoder 를 사용하여 인코딩에 사용했던 모습의 데이터를 추출하는 것을 해보았다. 보통 클라이언트에서 JWT 를 디코딩할 일은 별로 없지만, 우연히 이번에 해봐야할 이유가 생겨서 배우게 되었다. 의외로 간단하게 할 수 있어서 써드파티 라이브러리를 추가할 필요는 없을 것 같다.
'NotePad' 카테고리의 다른 글
[Flutter] CocoaPods could not find compatible versions for pod "NMapsMap" (0) | 2024.08.28 |
---|---|
[MediaPipe] Hand Landmark 적용 과정 정리 (0) | 2023.11.17 |
MusicXML 4.0 Tutorial - File Structure (0) | 2022.09.21 |
MusicXML 4.0 Tutorial - "Hello World" (0) | 2022.09.20 |
[음악] 음자리표 (Time Signature) (0) | 2022.09.20 |