Firebase 예시로 살펴보는 JWT

Category
Backend
Tags
JWT
Published
May 10, 2025
Last updated
Last updated May 12, 2025
 

JWT의 구조

JSON Web Token(JWT)은 세 부분으로 나뉘어 있으며, .(dot)으로 연결됩니다
https://velopert.com/2389

Header

헤더(Header)에는 토큰의 타입과 서명 알고리즘 정보가 들어갑니다. 일반적으로 두 개의 필드를 포함합니다.
{ "alg": "HS256", // 서명에 사용된 해싱 알고리즘 (예: HS256[SHA256], RS256) "typ": "JWT" // 토큰 타입 (항상 "JWT"), 생략가능 }
 

Payload

페이로드(Payload)는 실제 토큰에 담길 정보(클레임, claim)를 포함합니다. 클레임은 name: value의 한 쌍으로 이루어집니다.
클레임은 크게 세 종류로 나뉩니다:

등록된 클레임(Registered Claims)

  • iss: 토큰 발급자 (issuer)
  • sub: 토큰 제목 (subject)
  • aud: 토큰 대상자 (audience)
  • iat: 토큰이 발급된 시간 (issued at), 이 값을 사용하여 토큰의 age 가 얼마나 되었는지 판단 할 수 있습니다.
  • exp: 토큰의 만료시간 (expiraton), 시간은 NumericDate 형식으로 되어있어야 하며 (예: 1480849147370) 언제나 현재 시간보다 이후로 설정되어있어야합니다.
  • nbf: Not Before 를 의미하며, 토큰의 활성 날짜와 비슷한 개념입니다. 여기에도 NumericDate 형식으로 날짜를 지정하며, 이 날짜가 지나기 전까지는 토큰이 처리되지 않습니다.
  • jti: JWT의 고유 식별자로서, 주로 중복적인 처리를 방지하기 위하여 사용됩니다. 일회용 토큰에 사용하면 유용합니다.

공개 클레임(Public Claims)

공개 클레임들은 충돌이 방지된 이름을 가져야 합니다. 그래서 주로 URI 형식으로 지어집니다
// 예시 { "blog.wibaek.com": true }

비공개 클레임(Private Claims)

발행자와 소비자가 임의로 합의한 커스텀 필드
// 예시 { "iss": "blog.wibaek.com", // 토큰 발행자 "sub": "wibaek", // 토큰 주체 "aud": "api.wibaek.com", // 토큰 대상 "iat": 1690000000, // 발행 시각 (Unix timestamp) "exp": 1690003600, // 만료 시각 "wibaek.com": true, // 공개 클레임 "role": "admin" // 비공개 클레임 }

Signature

서명(Signature)은 헤더와 페이로드의 무결성을 검증하기 위해 사용됩니다. 서명을 생성하는 과정:
signature = BASE64URL-ENCODE( HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secretKey ) )
  • HS256 같은 대칭 키 알고리즘은 secretKey 하나로 생성/검증
  • RS256 같은 비대칭 키 알고리즘은 개인키(private key)로 서명, 공개키(public key)로 검증
서명이 토큰 마지막 부분에 붙어 JWT 전체의 위변조를 막습니다.
 

Firebase Authentication JWT로 알아보기

그럼 Firebase에서 발급해주는 JWT를 예시로 좀더 알아보겠습니다.

Header

{ "alg": "RS256", // 서명에 사용된 알고리즘 "kid": "N2BY0A" // Firebase가 관리하는 공개키 키 식별자(key ID) }
typ은 생략되어 있고, firebase만의 특별한 식별자인 kid가 들어가 있습니다.

Payload

{ "iss": "https://session.firebase.google.com/soma-projects", // 토큰 발행자 "sub": "312dfwqDSbhh4w56davgt43", "aud": "soma-projects", // 토큰 대상 "iat": 1746878028, // 발행 시각 (Unix timestamp) "exp": 1747310028, // 만료 시각 (5일) "admin": true, "auth_time": 1746878025, "user_id": "abcde", "email": "[email protected]", "email_verified": false, "firebase": { "identities": { "email": [ "[email protected]" ] }, "sign_in_provider": "password" } }
등록 클레임은 iss, sub, aud, iat, exp가 등록되어 있습니다. 공개 클레임은 별도로 없으며 여러 비공개 클레임들로 페이로드에 정보를 저장하고 있습니다.

Signature

RSASHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), Public Key, Private Key ) // 를 BASE64 디코딩한 값
시그니처는 RSASHA256를 이용하고 있는 것을 볼 수 있습니다.

Reference