Files
llm-wiki/raw/branch-notes/feature-keycloak-refresh-token-rotation.md
T

30 KiB

title, source_type, status, id, kind, project, work_item, inherits, refines, overrides, depends_on, contract_packet, branch, parent_branch, related_projects, tags, created, target_merge, status_label, contract_packet_sha256
title source_type status id kind project work_item inherits refines overrides depends_on contract_packet branch parent_branch related_projects tags created target_merge status_label contract_packet_sha256
branch / feature-keycloak-refresh-token-rotation (Refresh token rotation + revocation) branch-note raw BR-KEYCLOAK-CHILD-579E54CC branch-child keycloak-patterns-overview WI-KEYCLOAK-PATTERNS-OVERVIEW-007
DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1
DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1
WI-KEYCLOAK-PATTERNS-OVERVIEW-004
1 feature-keycloak-refresh-token-rotation feature-keycloak-refresh-rotation-and-logout
keycloak-patterns
branch
keycloak-patterns
p2a
refresh-token
rotation
revocation
keycloak
2026-05-25 in-progress 41b3c869ae7eecc249938a19e9501c8b8cecdb11d589882f2babb6d10f63618a

branch: feature-keycloak-refresh-token-rotation — Refresh token rotation + revocation

Layer: raw/branch-notes/raw/branch-notes/feature-keycloak-refresh-rotation-and-logout Work Item branch의 child. 목적: refresh token rotation의 개념·정책·검증 계약 owner로서, 공식 확인된 Revoke Refresh Token 동작과 target-version 실험이 필요한 Refresh Token Max Reuse/reuse 결과를 구분한다. /revoke 계약과 JWT stateless 한계도 함께 정리한다. status_label: in-progress | review | merged | abandoned

부모 (필수)

raw/branch-notes/feature-keycloak-refresh-rotation-and-logout

브랜치 계약 패킷

  • 생성 시 프로젝트 개정: 1
  • 패킷 스키마: contract_packet: 1
  • 완료 조건: refresh rotation과 logout 후 session·token 무효화가 검증된다

상속한 프로젝트 결정

Decision Ref Project Summary Branch Application Source
DEC-KEYCLOAK-PATTERNS-OVERVIEW-SPA-CLIENT-001@1 AP1은 public client와 Authorization Code + PKCE를 사용한다 public SPA의 refresh token rotation·revocation 계약에 적용한다 raw/project-notes/keycloak-patterns-overview
DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1 done-bar는 E2E success와 signature security failure 재현·해결 evidence다 parent의 rotation·logout 검증을 위한 개념·실험 계약에 적용한다 raw/project-notes/keycloak-patterns-overview

브랜치 지역 결정

기존 branch-local 결정은 아래 ## Decision Evidence Map의 D-row가 소유하며 이 packet에서 복제하지 않는다.

Decision ID Decision Relation Supporting Claims Status

선언한 예외

Override ID Overrides Reason Approval Status

없음.

목표

P2A는 SPA가 refresh_token을 보유하므로 탈취 시 공격자가 access_token을 계속 갱신할 수 있다. 공식 자료로 확인된 rotation 계약은 사용된 refresh token을 무효화하고 새 refresh token을 발급한다는 범위까지다(KC-RTROT-C1/C2). 이미 사용한 토큰을 다시 제출했을 때 후속 토큰까지 무효화되는지, 그 범위가 token family 전체인지, Max Reuse 값별 의미가 무엇인지는 target Keycloak 버전의 실행 실험으로만 확정한다.

핵심 질문:

  • Keycloak에서 rotation을 켜는 정확한 설정 항목과 위치는?
  • 이미 사용한 refresh token을 다시 제출하면 어떤 토큰·세션이 무효화되는가? (Max Reuse=01 비교 관찰)
  • /protocol/openid-connect/revoke endpoint 사용 방법?
  • logout 시 access_token / refresh_token / session을 어떻게 정리?
  • 함정: JWT access_token은 stateless — revoke를 호출해도 만료까지 검증을 통과한다. 즉시성 확보 방법은?

본 sub-sub-branch는 Keycloak Realm Settings 경로 + rotation flow + revocation endpoint + logout 정리 + stateless 한계를 정리.

  • 이슈: (학습 노트, 이슈 없음)
  • PR: (구현 없음)

범위

포함 범위

본 sub-sub-branch 는 P2A 개념·계약 정리(documented-only). "무엇이 어떻게 동작하는가 + 어떤 설정/파라미터 계약인가" 까지만 다루고, 실제 docker-compose 시연·실측은 cousin(다른 phase) raw/branch-notes/feature-keycloak-refresh-rotation-and-logout (P3A) 에 위임한다.

  • Keycloak refresh token rotation 설정의 개념·계약: Revoke Refresh Token 토글 동작 + rotation flow(RT 1회 사용 후 무효화·새 토큰 발급) — KC-RTROT-C1/C2
  • reuse detection 결과에 대한 가설·검증 계약 — 후속 RT 유효성, 세션 상태, Max Reuse=0/1 차이를 P3A 실행 문서에서 관찰하며 family invalidation을 선결 사실로 두지 않음
  • /protocol/openid-connect/revoke endpoint 의 RFC 7009 request/response 계약 (token/token_type_hint, refresh↔access 무효화 SHOULD) — RFC7009-C1~C4
  • JWT stateless access token 의 revoke 즉시성 한계 + 대응 옵션(짧은 TTL / introspection / blacklist / opaque) 트레이드오프 — RFC7009-C5~C7
  • RP-Initiated(front-channel) logout 파라미터 계약(id_token_hint, post_logout_redirect_uri, Valid Post Logout Redirect URIs) — KC-LOGOUT-C1~C7
  • 짧은 access token TTL 로 revoke 즉시성을 완화하는 설계 근거(RFC 자신의 short-lived-token 대안) — RFC7009-C6

제외 범위

의도적으로 제외한 것. 면접 등에서 "이건 범위에 없었습니다"라고 답할 근거.

  • 실제 rotation/revoke/logout 의 docker-compose 시연·실측 — cousin(P3A) raw/branch-notes/feature-keycloak-refresh-rotation-and-logout 소유
  • backend 매 요청 introspection 호출(stateless 포기 패턴) — 한계만 인지, 채택 안 함
  • distributed token blacklist 캐시(Redis 등) 운영 패턴
  • Keycloak custom SPI / event listener
  • back-channel logout 수신 backend 구현과 provider-trigger E2E — 현재 두 refresh note 모두 범위 밖. 필요 시 공식 spec·framework 근거를 갖춘 전용 branch를 새로 만들어야 하며 현재 endpoint 존재를 가정하지 않음
  • opaque / reference token 으로의 전환(Keycloak 지원하나 본 학습 범위 외)

근거 (필수, 최소 1개+)

TODO

각 항목 옆에 증거 등급 표기: actually-implemented | locally-verified | prod-verified | documented-only | planned | needs-confirmation

  • Keycloak Realm Settings → Tokens 탭 항목 — 등급: documented-only
    • Revoke Refresh Token: ON — refresh 사용 후 해당 토큰 무효화
    • Refresh Token Max Reuse: target UI에서 필드 존재를 확인한 뒤 0과 1을 실험 입력값으로 비교. 사전에 각 값의 의미를 부여하지 않음
    • SSO Session Idle: 짧게 (예: 30분) — 일정 시간 미사용 시 세션 만료
    • SSO Session Max: 강제 만료 시간 (예: 10h)
    • Access Token Lifespan: 5~15분 (짧을수록 revoke 즉시성 향상)
    • Client Session Idle / Client Session Max: client별 override
  • Refresh Token Rotation flow — 등급: documented-only
    1) SPA가 RT_1으로 /token (grant_type=refresh_token) 호출
    2) Keycloak: RT_1 검증 → invalidate → AT_2 + RT_2 반환
    3) SPA가 RT_2로 다음 갱신 → RT_2 invalidate → AT_3 + RT_3
    
  • Reuse Detection 결과 가설 검증 — 등급: needs-confirmation
    • 공격자가 RT_1을 탈취하고 사용 → AT_2 + RT_2 받음
    • 정상 사용자가 (모르고) RT_1을 다시 사용 → RT_1 응답과 RT_2의 후속 사용 결과, realm session 상태를 각각 관찰
    • Max Reuse=01에서 같은 sequence를 실행해 후속 토큰 무효화 범위를 기록. family 전체 invalidation은 가능한 관찰 결과 중 하나일 뿐 기대값으로 고정하지 않음
  • Revoke endpoint 사용법 — 등급: documented-only
    POST /realms/<realm>/protocol/openid-connect/revoke
      token=<token>
      token_type_hint=refresh_token  (또는 access_token)
      client_id=<spa-client>
    
    • token/token_type_hint 파라미터 계약은 RFC 7009 §2.1 표준과 일치 — raw/official-docs/oauth2-token-revocation-rfc-7009 RFC7009-C3 (Keycloak 이 이 endpoint 를 실제로 RFC 7009 로 문서화하는지는 RFC7009-C1 의 "Does not prove" 참조 — 별도 vendor 확인 필요)
    • refresh_token revoke: RFC 상 SHOULD 로 관련 access token 도 함께 무효화될 수 있음(RFC7009-C4) — MUST 아님, AS 지원 여부에 달림
    • access_token revoke: Keycloak은 introspection 시 invalid 응답, 그러나 JWT를 stateless로 검증하는 backend는 모름 (RFC7009-C5/C7, 아래 함정 참조)
  • Logout 시 토큰 정리 — 등급: documented-only
    • (a) Front-channel logout: /protocol/openid-connect/logout?post_logout_redirect_uri=...&id_token_hint=<id_token> — 브라우저 redirect로 Keycloak 세션 종료
    • (b) Back-channel logout: Keycloak client 설정 필드의 존재만 기록. 수신 endpoint와 provider-trigger E2E는 현재 범위에 없고 구현을 가정하지 않음
    • (c) Refresh token revoke: 명시적으로 /revoke 호출
    • SPA가 메모리에서 토큰 삭제 + cookie clear도 추가
  • 함정: JWT access_token stateless 한계 — 등급: documented-only
    • JWT는 자체 서명 검증으로 valid 여부 판단 → backend가 revoke 사실을 모름raw/official-docs/oauth2-token-revocation-rfc-7009 RFC7009-C5 (self-contained access token 은 AS 와 추가 상호작용 없이 인가 판단)가 표준 근거
    • access_token 만료(exp)까지 backend는 valid로 통과시킴 — RFC7009-C5 (self-contained token 은 AS 상호작용 없이 검증) + RFC7009-C4 (access token 무효화는 AS 가 지원할 때만 SHOULD, MUST 아님)
    • 대응 옵션:
      1. 짧은 TTL (5~15분) — 가장 일반적
      2. Token Introspection (/protocol/openid-connect/token/introspect) — 매 요청마다 Keycloak에 질의 → stateless 이점 상실, 성능 저하
      3. Revocation list / blacklist — backend가 revoked jti 목록 캐싱 (운영 복잡)
      4. Reference token (opaque) — JWT 대신 opaque token + introspection (Keycloak 지원하나 본 학습 범위 외)
  • 함정 정리 — 등급: documented-only
    • Refresh Token Max Reuse의 0/양수 의미를 실험 없이 일반화하면 버전별 동작을 잘못 문서화할 수 있음
    • logout 시 id_token_hint 누락하면 prompt 떠서 UX 저하
    • rotation 활성화 후 SPA 코드가 옛 RT를 재사용하면 실패하거나 후속 RT/세션에 영향이 갈 수 있음 → 정확한 범위는 실행 결과로 기록
    • back-channel receiver가 없는 현재 scope에서 backend cache 무효화를 보장한다고 쓰지 않음

진행 중 메모

작업하며 떠오른 메모. 자유 형식.

  • Keycloak 25.x 기준 Realm Settings → Tokens 탭 UI 항목은 버전에 따라 라벨이 약간 달라질 수 있음. 실 구현(P3A) 시 정확한 라벨 재확인 필요.
  • "JWT는 revoke가 안 된다"는 표현은 정확히는 "Keycloak이 revoke를 알리지만 stateless backend가 그 사실을 가져오지 않으면 모른다"가 맞음. 짧은 TTL + rotation 조합으로 실용적 보안 확보.
  • Keycloak의 Backchannel Logout URL 설정 필드 존재와 실제 수신 구현은 별개다. 현재 문서들은 receiver endpoint를 구현·위임하지 않으며, 필요 시 전용 branch에서 spec/framework 지원부터 확인한다.

결정 사항 (decisions)

추후 면접/회고에서 "왜 이렇게 했나" 답할 근거. 대안과 함께 기록.

  • 2026-05-25 (수정 2026-07-18): Revoke Refresh Token: ON은 rotation 실험의 candidate profile로 유지한다. Refresh Token Max Reuse: 0은 1과 비교할 실험 입력값이며, 다른 값이 탐지를 약화시킨다는 의미는 target-version 결과 전에는 주장하지 않는다.
  • 2026-05-25: access_token revocation 즉시성은 **짧은 TTL(5~15분)**로 해결. introspection은 stateless 이점 상실 + 성능 저하로 학습 범위에서 권장 안 함.
  • 2026-07-18: back-channel logout receiver와 provider-trigger E2E는 P2A/P3A 두 refresh note 모두 범위 밖이다. 현재 cousin에 위임하지 않으며, 필요 시 전용 branch를 신설한다.

결정-근거 매핑

각 결정이 어떤 raw source claim 으로 뒷받침되는지 명시. 본 sub-sub-branch 는 documented-only. Revoke Refresh Token 토글의 동작은 이제 Keycloak 공식 doc 로 뒷받침되나(KC-RTROT-C1/C2), Refresh Token Max Reuse 필드명"재사용 시 family 전체 invalidate" 동작은 Keycloak 26.7.0 Server Admin Guide 전수 검색에서 verbatim 부재 확인(KC-RTROT-C6) → 해당 부분만 UNSUPPORTED_DECISION 유지, 실측은 P3A cousin 에 위임. 선택 조건 열(R2): "이 조건일 때 이 결정, 다른 조건이면 어떤 대안". 분기 없으면 N/A.

Decision ID Decision 선택 조건 (언제 이 결정 / 언제 대안) Supporting Claims Evidence Strength Open Risk
D1 rotation 정책·검증 profile ownerRevoke Refresh Token: ON을 candidate로 두고 Refresh Token Max Reuse=0/1을 비교 실험한다. 최종 값과 의미는 target-version 관찰 뒤 확정 SPA(public client)가 refresh token을 브라우저에 보유하는 P2A/P3A 배치에서 rotation을 평가. BFF/token-mediating backend(raw/branch-notes/feature-keycloak-bff-vs-spa-direct)에서는 위협 모델이 달라 재평가. 병렬 refresh가 필요한 client는 suppress-refresh-token-rotation executor 예외(KC-RTROT-C3) 검토 raw/official-docs/keycloak-refresh-token-rotation-sessions-official.md#KC-RTROT-C1, #KC-RTROT-C2, raw/official-docs/oauth-v2-1-draft-ietf.md#OA21-C3, raw/official-docs/oauth2-browser-based-apps-ietf-draft.md#OAUTH-BBA-C3. Max Reuse 필드·값 의미·family 동작은 UNSUPPORTED_DECISION(KC-RTROT-C6) official-vendor-doc + official-standard + needs-confirmation (Max Reuse semantics) target UI/export에서 필드와 내부 key를 확인하고 0/1에서 동일 reuse sequence를 실행. family invalidation 여부는 결과값으로만 기록
D2 access token revocation 즉시성은 짧은 TTL(5~15분) 로 해결, introspection 패턴은 stateless 이점 상실로 권장 안 함 stateless JWT 검증(Spring RS)을 유지하는 한 → 짧은 TTL. "초 단위 즉시 무효화"가 hard requirement 면 → introspection 또는 opaque/reference token(stateless 포기 + 성능 비용) raw/official-docs/oauth2-token-revocation-rfc-7009.md#RFC7009-C5 (self-contained/JWT access token 은 AS 와 추가 상호작용 없이 검증 → revoke 즉시 반영 안 될 수 있음) + #RFC7009-C6 (짧은 수명 access token 이 RFC 자신의 설계 대안) + #RFC7009-C4 (access token 무효화는 AS 가 access token revocation 을 지원할 때만 SHOULD — 미지원/self-contained 시 즉시 무효화 안 됨). 방향성은 official-standard 근거 보유. 구체적 수치 "5~15분" 은 RFC 가 분 단위를 제시 안 하므로 UNSUPPORTED_IMPL_DECISION (trade-off: 짧을수록 안전하나 refresh 왕복/서버 부하↑ — 5~15분은 임의 균형점) official-standard (방향성) + UNSUPPORTED_IMPL_DECISION (TTL 수치) Keycloak 이 access token revocation(RFC7009 §2 SHOULD)을 실제 지원하는지 확인 + OWASP/Keycloak 공식 권장 TTL 구간 raw 추가로 수치 보강
D3 RP-Initiated logout 파라미터 계약까지만 소유. back-channel receiver 구현·provider-trigger E2E는 현재 scope 밖이며 endpoint를 가정하지 않음 현재 요구는 브라우저 logout과 revoke 계약 학습. backend cache 즉시 무효화가 별도 요구가 되면 전용 branch에서 OIDC Back-Channel Logout spec과 framework 지원을 확보한 뒤 설계 raw/official-docs/keycloak-oidc-logout-endpoint-official.md#KC-LOGOUT-C7 (설정 필드 존재만 증명) + UNSUPPORTED_DECISION (receiver 미설계) official-vendor-doc (field only) + scoped out receiver가 구현됐다는 인상을 주는 링크·예상 endpoint를 두지 않음
D4 reuse 결과 검증 계약 — RT_1 사용 후 무효화·AT_2+RT_2 발급까지는 공식 계약, RT_1 재사용 응답과 RT_2/realm session 상태는 관찰 항목 D1 profile의 0/1 각각에 동일 sequence 적용. family 전체 invalidation은 가능한 결과 중 하나이며 expected fact가 아님 raw/official-docs/keycloak-refresh-token-rotation-sessions-official.md#KC-RTROT-C2 + raw/official-docs/oauth-v2-1-draft-ietf.md#OA21-C3 + UNSUPPORTED_DECISION(KC-RTROT-C6) official-vendor-doc (초기 rotation) + needs-confirmation (reuse impact) P3A 실행 owner가 RT_1 재사용 status, RT_2 후속 status, session 상태를 분리 기록해야 함

구현 가이드

결정 (Decisions) 이 "무엇 을 할 것인가" 라면, 본 §는 "어디에 어떻게 구현될 것인가" 의 사전 명세 — 다음 구현자(P3A cousin)가 되묻지 않아도 설정·호출을 작성할 수 있는 수준. 본 노트는 documented-only 이므로 각 항목은 설정/파라미터 계약까지이며, 실측 승격은 Claims To Verify + P3A cousin 소관.

3-rule: (R1) 각 cell 은 Decision ID + Supporting Claim ID trace, (R2) 근거 없는 detail 은 UNSUPPORTED_IMPL_DECISION + trade-off 한 줄, (R3) 본 branch 결정 범위 밖은 남기지 않음.

1. Keycloak Realm Settings — rotation & timeout 설정 계약

Trace: D1(KC-RTROT-C1/C2) + D2(KC-RTROT-C4) — Realm Settings → Sessions/Tokens 탭.

  • UNSUPPORTED_IMPL_DECISION: Refresh Token Max Reuse 필드명·0/1 의미·reuse 후 영향(KC-RTROT-C6 doc text 부재 — admin UI/export와 실험 필요) / Access Token Lifespan의 "5~15분" 수치(RFC·Keycloak doc 모두 분 단위 미제시).
설정 위치 (Realm Settings) 근거 / 상태
Revoke Refresh Token Sessions/Tokens 탭 Enabled KC-RTROT-C1 — documented
Refresh Token Max Reuse Tokens 탭 (노출 여부 포함 확인) 0과 1을 각각 실험 UNSUPPORTED_IMPL_DECISION — 필드·값 의미 doc text 부재(KC-RTROT-C6), UI/export + runtime 비교
Access Token Lifespan Tokens 탭 5~15분 KC-RTROT-C4(설정 존재) + UNSUPPORTED_IMPL_DECISION(수치)
SSO Session Idle / SSO Session Max Sessions 탭 프로젝트값(예: 30m / 10h) KC-RTROT-C4 — documented
Client Session Idle / Client Session Max Sessions 탭 SSO 값보다 짧게(client override) KC-RTROT-C4 — documented

2. Revoke endpoint 호출 계약 (RFC 7009)

Trace: D2 + RFC7009-C1~C4.

  • UNSUPPORTED_IMPL_DECISION: Keycloak 이 이 endpoint 를 RFC 7009 로 문서화/준수한다는 명시는 vendor 확인 필요(RFC7009-C1 "Does not prove"). 여기서는 RFC 표준 계약 형태만 고정.
POST /realms/<realm>/protocol/openid-connect/revoke
  token=<token>                         # REQUIRED (RFC7009-C2)
  token_type_hint=refresh_token|access_token   # OPTIONAL, 서버 조회 최적화용 (RFC7009-C3)
  client_id=<spa-client>                # client 인증
  • refresh_token revoke → AS 가 access token revocation 을 지원하면 관련 access token 도 SHOULD 함께 무효화(RFC7009-C4 — MUST 아님).
  • access_token revoke → Keycloak introspection 은 invalid 로 응답하나, JWT 를 stateless 로 검증하는 backend 는 그 사실을 모름(§4 참조).

3. Front-channel(RP-Initiated) logout 파라미터 계약

Trace: KC-LOGOUT-C1~C7 (In-scope logout; back-channel 수신 은 D3 로 out of scope).

요소 계약 근거
endpoint /realms/<realm>/protocol/openid-connect/logout (= end_session_endpoint) KC-LOGOUT-C1/C2
id_token_hint 없으면 로그아웃 confirm UI 가 뜰 수 있음 → UX 위해 전달 권장 KC-LOGOUT-C3
post_logout_redirect_uri 제공 시 자동 redirect. 단 client_id 또는 id_token_hint 동반 필수 + client 의 Valid Post Logout Redirect URIs 와 매칭 필요 KC-LOGOUT-C4/C5/C6
Backchannel Logout URL (client 설정) 필드 정의만 in-scope. receiver endpoint와 provider-trigger E2E는 현재 존재를 가정하지 않으며 별도 요구 시 전용 branch 필요 KC-LOGOUT-C7

4. Stateless JWT access token 즉시성 완화 config

Trace: D2 + RFC7009-C5/C6/C7.

  • UNSUPPORTED_IMPL_DECISION: TTL 수치(§1 과 동일 trade-off).
  • backend(Spring RS)는 서명 + iss/aud/exp 만 검증 → revoke 사실을 모름(RFC7009-C5). exp 만료까지 valid 통과(RFC7009-C5 self-contained + RFC7009-C4 조건부 SHOULD).
  • 짧은 TTL = RFC 자신이 제시하는 설계 대안(RFC7009-C6). 채택.
대응 옵션 stateless 유지? 비용 본 노트 판정
짧은 TTL (5~15분) 유지 revoke 후 최대 TTL 만큼 노출 창 채택 (RFC7009-C6)
Token Introspection (매 요청) 포기 매 요청 Keycloak 왕복·성능↓ 한계만 인지, 미채택
Revocation list / jti blacklist 부분 backend 캐시 운영 복잡 out of scope
Opaque/reference token 포기 introspection 상시 out of scope

엣지·실패·의존

R4 캡처용. 정상 경로 외에 구현 중 부딪힐 실패/엣지/다른 계약 의존을 미리 열거.

  • 실패·엣지 경로:
    • RT 캐시 후 옛 RT 재사용 → RT_1 요청이 실패하고 후속 RT/세션에도 영향이 갈 수 있음. 정확한 범위는 D4 실험으로 관찰. 클라이언트는 in-flight refresh를 단일 진입점으로 직렬화한다.
    • 동시 silent renew race → 동일 RT 동시 제출은 D4 관찰을 오염시킬 수 있음. 0/1 각 실험에서 단일 refresh 진입점을 보장하고 manual 시연 시 silent renew를 일시 중단한다.
    • logout id_token_hint 누락 → confirm prompt 로 UX 저하(KC-LOGOUT-C3). 기대: id_token 보관 후 전달.
    • post_logout_redirect_uri 미등록Valid Post Logout Redirect URIs 매칭 실패로 redirect 거부(KC-LOGOUT-C6). 기대: client 설정에 사전 등록.
    • access_token revoke 직후 만료 전 호출 → 200 통과(stateless JWT, RFC7009-C5) — 함정(의도된 한계). 기대: exp 까지 유효, TTL 후 401.
    • back-channel receiver 부재 → 현재 범위에서는 backend session/cache의 즉시 무효화를 보장하지 않는다. 필요 시 전용 branch를 생성한다.
  • 다른 계약 의존:

검증해야 할 주장

공식 문서나 사례는 근거지만, 내 프로젝트에서의 동작을 자동으로 보장하지 않는다.

Claim Why uncertain How to verify Status
Keycloak Realm Settings → Tokens 탭에 Revoke Refresh Token 토글과 Refresh Token Max Reuse 입력이 정확히 그 라벨로 존재 Keycloak 버전마다 admin UI 라벨이 달라질 수 있음; cited raw 에서 verbatim 미회수 Keycloak 25.x docker 컨테이너 실행 후 admin UI 캡처 + Server Admin Guide raw source 발췌 추가 needs-confirmation
Refresh Token Max Reuse=01에서 RT 재사용 결과가 어떻게 다른지(후속 RT·realm session 포함) 필드·값 의미와 family invalidation 메커니즘이 cited raw에 verbatim 없음 각 값으로 realm을 재설정한 뒤 RT_1 사용→RT_2 발급→RT_1 재사용→RT_2 후속 사용→session 상태를 동일 순서로 기록 needs-confirmation
/protocol/openid-connect/revoke 엔드포인트가 RFC 7009 Token Revocation 을 준수한다 RFC 7009 의 raw source 부재; Keycloak 의 RFC 준수 여부 verbatim 인용 없음 RFC 7009 raw 발췌 후 Keycloak Server Admin Guide 의 "Token Revocation" 섹션과 cross-check needs-confirmation
JWT stateless backend 가 access_token revoke 사실을 모름 — 만료 전 검증 통과 OAuth 2.1 / PKCE RFC 에 stateless JWT introspection 트레이드오프의 verbatim 인용 없음 Spring Security Resource Server 로 JWT 검증 설정 후, revoke 직후 동일 token 으로 호출 → 200 응답 확인 (TTL 5분) planned
RP-Initiated logout 파라미터가 target Keycloak에서 문서 계약대로 동작하는지 공식 파라미터 계약은 있으나 runtime 미검증. back-channel receiver는 본 claim과 scope에 포함하지 않음 front-channel logout만 실행해 session 종료·redirect를 확인. back-channel 요구가 생기면 전용 branch에서 별도 검증 needs-confirmation

마주친 문제

  • 이슈 1: rotation 상태에서 SPA가 옛 refresh_token을 재시도하면 정상 사용자 흐름도 실패할 수 있음.
    • 원인 가설: reuse 처리 범위가 정상/공격 주체를 구분하지 않을 수 있음. 후속 RT·session 영향은 target-version 실험 전 확정하지 않음
    • 시도: (구현 없음)
    • 해결: SPA가 refresh 진행 중에는 단일 진입점으로 직렬화 (in-flight refresh promise 공유) — documented-only

묶음

본 sub-sub-branch 는 leaf — 자식 자료 없음. Phase 3 P3A 실 구현 또는 외부 산출물 단계에서 errors / interview prep / lectures 가 누적되면 본 섹션에서 그룹화.

오류 기록 (이 sub-sub-branch 작업 중 발생)

  • (없음 — 현재 documented-only 단계)

면접 준비 (이 작업에서 나올 수 있는 면접 질문)

  • (없음 — Phase 3 실 구현 단계에 누적)

관련 일일 노트

완료 후 정리

머지/종료 시점에 채움. /ingest가 이 섹션을 기준으로 wiki/projects/에 추출.

  • PR 링크: (미구현 — 문서까지만)
  • 리뷰 메모:
  • 머지 결과 / 배포 환경: 없음 (P2A는 documented-only 범위)
  • wiki 추출 대상: 현 단계 없음. 추후 wiki/concepts/refresh-token-rotation-revocation.md로 합성 후보 (다른 패턴과 공통).
  • 추출하지 않을 항목: P2A 구현 없음. documented-only 유지.