본문으로 바로가기

JWT(JSON Web Token) 구조

category ETC 2021. 12. 30. 13:24

1. JWT

  • 클라이언트와 서버, 서비스와 서비스 사이 통신 시 권한 인가(Authorization)를 위해 사용하는 토큰
  • Bearer Authentication (JWT 혹은 OAuth에 대한 토큰을 사용하면 Bearer 타입 인증)
  • 회원 인증정보 교류할 때 많이 사용합니다.
  • 확장성이 좋아 토큰 기반 인증을 지원하는 다른 서비스에 접근할 수 있습니다.
  • 사용자 인증에 필요한 모든 정보는 토큰 자체에 포함하기 때문에 별도의 인증 저장소(인증서버, DB, 세션 등)가 필요 없습니다.
  • 담을 내용에 따라 크기가 커질 수 있고, 생성 비용이 많이 듭니다. (그러나 요즘 컴퓨팅 성능으로는 신경 쓰지 않아도 될 정도입니다.) 

2. JWT 구조

  • JWT는 .을 기준으로 헤더(Header) - 내용(Payload) - 서명(Signature)으로 구성되어있습니다.
  • Json으로 되어있는 데이터를 Base64(Url Safe) Encode, Hmac 등을 이용하여 인코딩 후 .(dot)으로 구분하여 토큰 값을 만들어 냅니다.
  • 아래의 사이트를 이용해 Base64 url encode, decode 확인해보세요.

Header.Payload.Signature

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJ0ZXN0IiwiaWF0IjoxNjM5OTg1NTg5LCJleHAiOjE2NDAwNzE5ODksInN1YiI6ImhlbGxvIEp3dCJ9.7q0elwhYCoHJUTS17HPqUBTwL8C2PsV57ME0-qU5hkM

 

Header Base64 Encode

base64url encode header

 

Header

  • 헤더는 토큰의 타입 알고리즘(변조 방지를 위한)을 지정하는 정보를 포함합니다.
  • Base64(Url Safe) Encode를 이용해 값을 생성합니다.
  • 따라서 Base64 Decode를 하면 값을 확인할 수 있습니다.

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

{"typ":"JWT","alg":"HS256"}

 

typ = 타입

alg = 사용한 알고리즘 ( HS256 = HMAC-SHA256 )

Payload

  • 토큰에 담을 정보가 들어갑니다.
  • 정보의 한 뭉치를 클레임(claim)이라고 합니다.
  • claim은 key-value로 이루어져 있습니다.
  • 클레임의 종류는 등록된 클레임, 공개 클레임, 비공개 클레임으로 나누어져 있습니다.
  • Base64(Url Safe) Encode를 이용해 값을 생성합니다.
  • 따라서 Base64 Decode를 하면 값을 확인할 수 있습니다.

eyJpc3MiOiJ0ZXN0IiwiaWF0IjoxNjM5OTg1NTg5LCJleHAiOjE2NDAwNzE5ODksInN1YiI6ImhlbGxvIEp3dCJ9

{"iss":"test","iat":1639985589,"exp":1640071989,"sub":"hello Jwt"}

 

iss = 발급자 (issuer) 

iat = 토큰 발급 시간 (issued at)

exp = 토큰 만료 시간 (expiraton)

sub = 토큰 제목 (subject)

 

그 외에도 

aud(대상), nbf(활성 일자), jti(고유식별자)가 존재하며

사용자 맘대로 key-value 형태로 저장할 수도 있습니다. -> 비공개 클레임

 

Claim

[등록된 (registered) 클레임]

등록된 클레임들은 서비스에서 필요한 정보들이 아닌, 토큰에 대한 정보들을 담기 위하여 이름이 이미 정해진 클레임들입니다. 

iss = 발급자 (issuer) 

iat = 토큰 발급 시간 (issued at)

exp = 토큰 만료 시간 (expiraton)

sub = 토큰 제목 (subject)

aud = 대상 (audience)

nbf = 활성 일자 (Not Before)

jti = 고유식별자, 중복적인 처리를 방지하기 위하여 사용, 따라서 일회용 토큰에 사용하면 유용합니다.

 

[공개 (public) 클레임]

공개 클레임들은 충돌이 방지된 (collision-resistant) 이름을 가지고 있어야 합니다. 충돌을 방지하기 위해서 클레임 이름을 URI 형식으로 생성합니다.

{"https://veneas.tistory.com/jwt_claims/auth_check":true}

 

[비공개 (private) 클레임]

양 측간에 협의하에 맘대로 key, value를 지정하여 사용하는 클레임입니다. 공개 클레임과는 달리 이름이 중복되어 충돌이 될 수 있으니 사용 시 유의해야 합니다.

{"name":"veneas"}

Signature

7q0elwhYCoHJUTS17HPqUBTwL8C2PsV57ME0-qU5hkM

HMACSHA256(

  base64UrlEncode(header) + "." +

  base64UrlEncode(payload),

  your-256-bit-secret

)

 

secret키는 testPassword를 사용하여 값을 만들었습니다.

 

HMAC-SHA256(HeaderToken + "." + PayloadToken) + Base64 (Signature 대조하여 변조 확인)

[ HeaderToken + "." + PayloadToken ] -> HMAC-SHA256 + Base64 URL Encode

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJ0ZXN0IiwiaWF0IjoxNjM5OTg1NTg5LCJleHAiOjE2NDAwNzE5ODksInN1YiI6ImhlbGxvIEp3dCJ9 

Signature 생성

 

3. 정리

  • JWT는 Header, Payload, Signature로 구성되어 있습니다. 
  • Header는 토큰 타입과 Signature를 만들 때 사용한 알고리즘 값을 가지고 있습니다.
  • Payload는 토큰에 담을 정보들(Claim)이 들어갑니다.
  • Header와 Payload 값은 Base64 Url Encode로 생성합니다.
  • Signature는 Header와 Payload 그리고 Header에 지정된 알고리즘으로 생성하여 변조를 확인할 때 사용합니다.