본문으로 건너뛰기
김신건의 로그

[Auth] JWT: 구조, 서명, 만료, refresh token

· 수정 · 📖 약 2분 · 686자/단어 #jwt #auth #security #backend
JWT, JSON Web Token, JWS, JWE, JWA, Bearer token, Refresh token, Access token, RS256, HS256

정의

JWT (JSON Web Token) (RFC 7519) 은 base64url 인코딩된 JSON + 서명 형태의 self-contained token. 서버가 세션 저장 없이 클레임 검증 가능.

구조: 3 부분

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI0MiIsIm5hbWUiOiJrb2EiLCJleHAiOjE3MjAxMjM0NTZ9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
↑ header                                  ↑ payload                                            ↑ signature
부분형식
Header{ "alg": "HS256", "typ": "JWT" }
Payload{ "sub": "42", "name": "koa", "exp": 1720123456 }
SignatureHMAC-SHA256(base64(header) + ”.” + base64(payload), secret)

표준 클레임

클레임의미
ississuer
subsubject (user ID)
audaudience
exp만료 시각 (Unix epoch)
nbfnot before
iatissued at
jtiJWT ID (unique, replay 방지)

서명 알고리즘

Alg종류비고
HS256/384/512HMAC (대칭)양측이 같은 secret. 내부
RS256/384/512RSA (비대칭)private 으로 sign, public 으로 verify
ES256/384/512ECDSA짧고 빠름
EdDSAEd25519가장 빠름, 안전
none서명 없음사용 금지 (취약점 다수)

WARNING

alg: none 을 받는 라이브러리는 치명적 취약점. 항상 허용 alg 화이트리스트.

흐름

sequenceDiagram
    autonumber
    participant C as Client
    participant Auth as Auth Server
    participant API as API Server

    C->>Auth: POST /login (id, password)
    Auth->>Auth: 검증 + JWT 생성
    Auth-->>C: { access_token, refresh_token }
    C->>API: GET /me<br/>Authorization: Bearer <jwt>
    API->>API: JWT 검증 (서명 + exp)
    API-->>C: 200 OK
    Note over C: 만료 임박
    C->>Auth: POST /refresh (refresh_token)
    Auth-->>C: 새 access_token

Access Token vs Refresh Token

항목Access TokenRefresh Token
수명짧음 (5분 ~ 1시간)길음 (7일 ~ 30일)
저장메모리 (브라우저 SPA)HttpOnly cookie 또는 안전한 저장
매 요청 전송갱신 시만
탈취 영향짧은 시간 피해큰 피해, 반드시 HttpOnly
Revoke만료까지 어려움DB 에 저장 + revoke 가능

IMPORTANT

Access token 을 localStorage 에 저장 하면 XSS 시 즉시 탈취. 메모리 + 새로고침 시 refresh 패턴이 정통.

Stateless vs Stateful

Session (stateful)JWT (stateless)
서버 저장소필수불필요
Revoke즉시만료까지 어려움
스케일sticky session 필요수평 확장 자유
페이로드session ID 만 (작음)전체 클레임 (큼)
갱신서버 갱신새 JWT 발급

CAUTION

“JWT 가 항상 더 좋다” 는 미신. 작은 monolith 에서는 session 이 더 단순 + 즉시 revoke 가능. JWT 는 분산 + 마이크로서비스 + 모바일 SDK 에서 진가.

Revoke 전략 (Stateless 의 단점 보완)

flowchart TD
    Q{revoke 필요}
    Q --> A[짧은 exp + refresh<br/>대부분의 경우]
    Q --> B["Blacklist (Redis)<br/>jti 등록"]
    Q --> C[Versioning<br/>user.token_version<br/>JWT 안에 version]
    A --> Best[추천]
    B --> Heavy[캐시 부담]
    C --> Sync[DB 한 번 조회 필요]

XSS / CSRF 와의 관계

flowchart TD
    Store{저장 위치}
    Store --> A[localStorage] -->|XSS 시 탈취| Bad1[X]
    Store --> B[메모리 + HttpOnly cookie refresh] -->|XSS 영향 적음| Good[O]
    Store --> C[HttpOnly cookie + SameSite=Strict] -->|CSRF 안전 + XSS 안전| Best[권장]

IMPORTANT

Cookie 기반 이면 CSRF 방어 필요 (SameSite=Strict 또는 CSRF token). Bearer headerXSS 방어 가 중요.

흔한 함정

WARNING

  1. alg: none 허용 라이브러리 = 옛 라이브러리 일부. 즉시 업데이트.
  2. HS256 vs RS256 혼동 = 공개키를 secret 으로 오해해 서명 받으면 모든 토큰 위조 가능 (CVE 다수).
  3. 만료 너무 김 = 탈취 시 피해 큼. 15분 ~ 1시간 권장.
  4. secret 이 짧음 = secret 같이 무차별 공격 가능한 키. 32+ 바이트 랜덤.
  5. 민감 정보 페이로드 = JWT 는 암호화 아님 (base64 인코딩). password / 카드 번호 절대 금지.

JWE (암호화 변형)

JWT 가 서명만 이면 내용 노출. JWE암호화 까지. 그러나 느리고 복잡. 대부분의 경우 민감 정보를 페이로드에 안 넣고 JWS (서명만) 만으로 충분.

관련 위키

이 글의 용어 (5개)
[Auth] CSRF: 위조 요청 공격과 방어auth-security
정의 CSRF (Cross-Site Request Forgery) 는 사용자가 로그인된 상태 에서 공격자가 만든 페이지 가 피해자 브라우저로 위조 요청 을 보내는 공격. 쿠키 기…
[Auth] OAuth 2.0 / 2.1: Authorization Code + PKCEauth-security
정의 OAuth 2.0 (RFC 6749, 2012) 은 제3자 앱이 사용자 동의로 자원에 접근 하게 하는 권한 위임 프레임워크. 인증 (authentication) 이 아니라 …
[Auth] OpenID Connect (OIDC): OAuth 위의 인증 레이어auth-security
정의 OpenID Connect (OIDC) 는 OAuth 2.0 위에 얹은 인증 (authentication) 표준. OAuth 가 권한 위임 (authorization), O…
[Auth] Session Cookie: HttpOnly, SameSite, Secure flagauth-security
정의 Session Cookie 는 서버가 발급한 임의 ID 를 쿠키에 보관. 매 요청 자동 첨부. 서버 측 세션 store (Redis, DB) 와 짝. [!IMPORTANT]…
[Network] CORS: Same-Origin Policy, preflight, credentialsnetwork
정의 CORS (Cross-Origin Resource Sharing) 는 Same-Origin Policy (SOP) 의 완화 메커니즘. 브라우저가 origin 이 다른 리소스…

💬 댓글

사이트 검색 / 명령어

검색

스크롤 = 확대/축소 · 드래그 = 이동 · 0 = 원래 크기 · ESC = 닫기