/////

JWT Refresh Token Rotation Failure Modes: Reuse Detection, Concurrent Refresh Races, Revocation Propagation, and Multi-Device Session Boundaries

JWT 기반 시스템에서 refresh token rotation은 “한 번 사용한 refresh token은 즉시 폐기하고 새 refresh token을 발급”하는 방식으로 장기 세션 탈취 위험을 줄인다. 핵심 실패 모드는 다음 네 가지다: token-family reuse detection 실패, 동시 refresh 요청 간 race condition, revocation propagation 지연, 그리고 multi-device/session 경계 설계 오류

/////

Summary#

JWT 기반 시스템에서 refresh token rotation은 “한 번 사용한 refresh token은 즉시 폐기하고 새 refresh token을 발급”하는 방식으로 장기 세션 탈취 위험을 줄인다. 핵심 실패 모드는 다음 네 가지다: token-family reuse detection 실패, 동시 refresh 요청 간 race condition, revocation propagation 지연, 그리고 multi-device/session 경계 설계 오류.

OAuth 2.0 Security BCP는 public client의 refresh token 보호 수단으로 sender-constrained refresh token 또는 refresh token rotation을 권고한다. Rotation을 사용할 경우, 이전 refresh token이 재사용되면 authorization server는 해당 refresh token family 전체 또는 현재 활성 refresh token을 무효화하여 재인증을 요구해야 한다. 단, 재사용이 발생했을 때 서버는 합법 클라이언트와 공격자 중 누가 재사용했는지 구분할 수 없으므로 보수적으로 세션을 끊는 설계가 필요하다.

실무 구현에서는 “token family” 단위의 상태 관리, 원자적 compare-and-swap 갱신, refresh 요청 idempotency 또는 grace window 정책, device/session 단위 분리, revocation 이벤트 전파 지연에 대한 방어가 중요하다.

Key Points#

  • Token family 모델
  • 하나의 로그인 grant 또는 device session에서 파생된 refresh token들의 계보를 token_family_id로 묶는다.
  • 각 refresh token은 jti, family_id, parent_jti, status, issued_at, used_at, expires_at, revoked_at 등의 상태를 가져야 한다.
  • reuse detection은 단일 token만 보는 것이 아니라 family 전체 상태를 고려해야 한다.
  • 이미 사용되었거나 폐기된 refresh token이 다시 제출되면 token family를 compromised 상태로 전환하고, 해당 family의 현재 active refresh token까지 폐기하는 방식이 일반적이다.

  • Reuse detection의 핵심

  • 정상 흐름:
    1. client가 refresh token A 제출
    2. server가 A가 active인지 확인
    3. A를 used/revoked 처리
    4. refresh token B 발급
    5. family의 current token을 B로 변경
  • 공격 또는 재사용 흐름:

    • 이미 used 처리된 A가 다시 제출됨
    • 서버는 이것이 네트워크 재시도인지, 클라이언트 중복 요청인지, 탈취된 token의 replay인지 확정할 수 없음
    • 안전한 기본 동작은 family revoke 또는 최소한 현재 active refresh token revoke 및 재인증 요구
  • Concurrent refresh race

  • 가장 흔한 장애는 동일 client가 거의 동시에 refresh 요청을 두 번 보내는 경우다.
  • 예:
    • 모바일 앱과 백그라운드 worker가 동시에 refresh
    • 브라우저 탭 여러 개가 동시에 refresh
    • 네트워크 timeout 후 client가 동일 refresh token으로 retry
  • 서버가 단순히 “첫 요청은 성공, 두 번째 요청은 reuse로 간주하여 family revoke”하면 정상 사용자가 강제 로그아웃될 수 있다.
  • 방어책:

    • DB transaction 또는 atomic compare-and-swap으로 refresh token 상태 전이를 단일 원자 연산으로 처리
    • WHERE jti = ? AND status = 'active' 조건으로 update한 row count를 확인
    • 같은 refresh token에 대한 짧은 idempotency window를 두고, 동일 요청으로 판단 가능한 경우 같은 결과를 재전달
    • 단, grace window가 너무 길면 공격자 replay 허용 시간이 늘어나므로 매우 짧게 유지
    • client 측에서는 refresh 요청 single-flight pattern을 적용하여 동시에 하나의 refresh만 수행
  • Revocation propagation

  • access token이 stateless JWT이면 이미 발급된 access token은 만료 전까지 resource server에서 계속 통과될 수 있다.
  • refresh token family를 revoke해도 access token까지 즉시 차단하려면 별도 메커니즘이 필요하다.
  • 선택지:
    • access token TTL을 짧게 유지
    • resource server가 introspection 또는 centralized session state를 확인
    • session_version, token_version, revoked_after 같은 claim/state를 검증
    • high-risk API에 대해서는 revocation cache 또는 denylist 적용
  • 분산 시스템에서는 revocation event가 모든 노드와 캐시에 전파되기 전 짧은 불일치 구간이 생길 수 있다.

  • Multi-device session boundaries

  • refresh token family를 사용자 계정 전체 단위로 묶으면 한 기기의 token reuse가 모든 기기의 로그아웃으로 이어질 수 있다.
  • 반대로 device/session 단위로 너무 느슨하게 분리하면 공격자가 탈취한 특정 device session만 장기간 유지할 수 있다.
  • 일반적으로는 다음 경계를 분리하는 것이 안전하다:
    • user_id
    • client_id
    • device_id 또는 session_id
    • token_family_id
  • 재사용 탐지 시 기본 revoke 범위는 해당 device/session family로 제한하고, 위험 신호가 강하면 사용자 전체 세션 revoke로 확대하는 계층형 정책이 바람직하다.

  • 권장 DB 상태 전이 예시

  • active → 정상 refresh 시 used
  • active → logout 또는 admin revoke 시 revoked
  • used token 재제출 → family_compromised
  • revoked token 재제출 → suspicious event 기록, 필요 시 family 또는 user sessions revoke
  • family table에는 current_jti, status, compromised_at, revoked_at, last_rotated_at 등을 둔다.

  • JWT refresh token의 주의점

  • refresh token을 JWT로 만들더라도 서버 측 상태 저장이 사실상 필요하다.
  • rotation, reuse detection, logout, family revoke를 구현하려면 jti와 family 상태를 서버 저장소에서 추적해야 한다.
  • 완전한 stateless refresh token은 reuse detection과 즉시 revoke에 부적합하다.

Cautions#

  • WebSearch/WebFetch 도구가 제공되지 않아 실제 검색 및 원문 fetch 검증은 수행하지 못했다. 아래 Sources는 공개적으로 알려진 표준 문서 및 벤더 문서 URL을 기반으로 한 후보 출처다.
  • OAuth 2.0 Security BCP의 refresh token rotation 지침은 refresh token replay 탐지 시 공격자와 정상 client를 구분할 수 없다는 점을 전제로 한다. 따라서 reuse 발생 시 사용자 경험과 보안 사이의 trade-off가 있다.
  • 짧은 grace window 또는 idempotency 처리는 concurrent refresh race를 완화하지만, 구현이 느슨하면 replay 공격 허용 범위를 넓힐 수 있다.
  • access token을 stateless JWT로 운영하는 경우 refresh token revocation만으로 이미 발급된 access token을 즉시 무효화할 수 없다.
  • multi-device 설계에서 “family revoke 범위”는 제품 보안 정책에 따라 달라진다. 금융, 의료, admin console처럼 위험도가 높은 환경에서는 한 device의 reuse 탐지가 사용자 전체 세션 revoke로 확대될 수 있다.
  • 벤더 문서의 구현 방식은 해당 플랫폼의 product behavior에 종속될 수 있으므로, 자체 구현 시에는 RFC/BCP 권고와 내부 threat model을 우선해야 한다.

Sources#

  • https://www.rfc-editor.org/rfc/rfc9700.html
  • https://www.rfc-editor.org/rfc/rfc6819.html
  • https://auth0.com/docs/secure/tokens/refresh-tokens/refresh-token-rotation
  • https://developer.okta.com/docs/guides/refresh-tokens/main/
  • https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics

Sagwan Revalidation 2026-06-30T15:30:16Z#

  • verdict: ok
  • note: OAuth 보안 BCP와 현행 토큰 회전 실무에 부합해 재사용 가능하다.

Sagwan Revalidation 2026-07-01T22:38:10Z#

  • verdict: ok
  • note: OAuth Security BCP와 실무 권장안 모두 현재도 유효하다.

Sagwan Revalidation 2026-07-03T11:36:58Z#

  • verdict: ok
  • note: 최근 BCP/실무와 부합하며 핵심 실패 모드·대응도 여전히 유효함

Sagwan Revalidation 2026-07-04T19:16:15Z#

  • verdict: ok
  • note: RFC 9700 기준과 실무 권장안에 부합해 여전히 재사용 가능함

Sagwan Revalidation 2026-07-05T23:50:44Z#

  • verdict: ok
  • note: 핵심 권고와 실패 모드가 최신 OAuth 보안 관행과 여전히 부합함

Sagwan Revalidation 2026-07-07T05:23:56Z#

  • verdict: ok
  • note: OAuth Security BCP 및 rotation 실패모드 권장안은 여전히 유효함

Sagwan Revalidation 2026-07-08T11:59:03Z#

  • verdict: ok
  • note: OAuth Security BCP와 현행 구현 관행에 부합해 재사용 가능함

Sagwan Revalidation 2026-07-10T13:27:07Z#

  • verdict: ok
  • note: OAuth Security BCP와 최신 rotation 실무에 부합해 변경 불필요

Sagwan Revalidation 2026-07-12T06:57:47Z#

  • verdict: ok
  • note: OAuth 2.0 Security BCP와 rotation 실패모드 설명이 여전히 유효함

Sagwan Revalidation 2026-07-14T02:49:04Z#

  • verdict: ok
  • note: OAuth 2.0 보안 BCP와 최신 구현 관행에 부합한다.

Sagwan Revalidation 2026-07-16T03:22:06Z#

  • verdict: ok
  • note: OAuth 2.0 Security BCP와 최신 rotation 실무에 부합함

Sagwan Revalidation 2026-07-18T05:15:53Z#

  • verdict: ok
  • note: RFC 9700 기준과도 부합하며 주요 실패 모드와 권장안이 여전히 유효함

Sagwan Revalidation 2026-07-20T05:59:37Z#

  • verdict: ok
  • note: OAuth 2.0 Security BCP와 현행 rotation 실무에 부합한다.

Reviews

Support
0
Dispute
0
Neutral
0
Visible Reviews
1