Files
llm-wiki/raw/branch-notes/feature-keycloak-token-mediating-access-handoff.md
T

13 KiB

title, source_type, status, id, kind, project, work_item, inherits, refines, overrides, depends_on, imports, delegates, accepts_delegations, contract_packet, contract_packet_sha256, branch, parent_branch, related_projects, tags, created, target_merge, status_label
title source_type status id kind project work_item inherits refines overrides depends_on imports delegates accepts_delegations contract_packet contract_packet_sha256 branch parent_branch related_projects tags created target_merge status_label
branch / feature-keycloak-token-mediating-access-handoff branch-note raw BR-KEYCLOAK-PATTERNS-OVERVIEW-009 project-work-item keycloak-patterns-overview WI-KEYCLOAK-PATTERNS-OVERVIEW-009
DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1
DEC-KEYCLOAK-PATTERNS-OVERVIEW-TOKEN-MEDIATING-001@1
WI-KEYCLOAK-PATTERNS-OVERVIEW-008
1 76cd5b845d8e9bd8eb75e0a2f2c46adad06c6b67eb9bf358ada252205ad86f82 feature-keycloak-token-mediating-access-handoff
keycloak-patterns-overview
branch
2026-07-24 in-progress

branch: feature-keycloak-token-mediating-access-handoff

부모 (필수)

브랜치 계약 패킷

  • 생성 시 프로젝트 개정: 1
  • 패킷 스키마: contract_packet: 1
  • 완료 조건: browser가 access token으로 API 200을 받고 refresh token은 network response에 존재하지 않는다

상속한 프로젝트 결정

Decision Ref Project Summary Branch Application Source
DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1 done-bar는 E2E success와 signature security failure 재현·해결 evidence다 WI-KEYCLOAK-PATTERNS-OVERVIEW-009 완료 조건에 적용 [[raw/project-notes/keycloak-patterns-overview]]
DEC-KEYCLOAK-PATTERNS-OVERVIEW-TOKEN-MEDIATING-001@1 AP2 backend가 token을 획득하고 access token만 browser에 전달한다 WI-KEYCLOAK-PATTERNS-OVERVIEW-009 완료 조건에 적용 [[raw/project-notes/keycloak-patterns-overview]]

브랜치 지역 결정

Decision ID Decision Relation Supporting Claims Status

선언한 예외

Override ID Overrides Reason Approval Status

가져온 artifact 계약

Artifact Ref Owner Producer Schema Ref

가져온 프로젝트 계약

Ref Owner 요약 Branch 적용

수신한 위임

Delegation Ref From Concern Status

가져온 흐름 단계

Stage Ref Order Owner Input Action Output

목표

  • WI-KEYCLOAK-PATTERNS-OVERVIEW-009의 완료 조건을 구현한다: browser가 access token으로 API 200을 받고 refresh token은 network response에 존재하지 않는다

범위

포함 범위

  • backend 가 획득한 토큰 중 access token 만 browser 로 handoff → browser 가 Resource Server 를 직접 호출(proxy 없음) 200.
  • refresh token 이 browser 로 가는 network response(응답 바디/헤더/쿠키)에 부재함을 확인(refresh 는 backend 만 보유).
  • 위 두 가지를 로컬 스택에서 네트워크 탭/응답 검사로 재현·검증.

제외 범위

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

  • backend 의 code→token 교환 + refresh 서버측 보관 자체WI-008(feature-keycloak-token-mediating-confidential-client) 소유. 본 branch 는 그 산출물(서버측 보관 access)을 browser 로 넘기는 경계만.
  • BFF(모든 요청 proxy) → AP3. 본 패턴은 proxy 없이 access 를 browser 에 위임(TMB 의 정의적 차이).
  • project decision registry 변경.

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

Source 정당화하는 결정
[[raw/official-docs/oauth2-browser-based-apps-ietf-draft]] D1·D2 — Token-Mediating Backend 정의: backend 가 confidential client 로 토큰 획득 후 access token 을 앱에 건네 RS 와 직접 통신(OAUTH-BBA-C2), BFF 대비 proxy 불필요·보안수준 낮음(OAUTH-BBA-C5), BFF 는 어떤 토큰도 browser 미노출(OAUTH-BBA-C1, 대비 근거)
[[raw/company-tech-blogs/curity-bff-pattern-spa]] D2 — token 을 browser 에 두는 것의 위험(대비 사례, company-case-study — 단독 official 단언 불가)
[[raw/branch-notes/feature-keycloak-token-mediating-confidential-client]] 의존 — WI-008 이 서버측에 보관한 access/refresh 를 consume

TODO

  • backend 가 access token 만 browser 로 전달하는 handoff 경로 구현 — 등급: planned
  • browser 가 그 access token 으로 /api 200(RS 직접 호출) — 등급: planned
  • refresh token 이 browser network response 에 부재함을 네트워크 탭/응답 바디로 확인 — 등급: planned

진행 중 메모

  • 본 branch 는 WI-008(획득·서버보관)에 의존하며, "browser 로 무엇을 넘기는가"의 경계만 결정. AP2 구현 코드 미존재(NO_GROUND_TRUTH) → 전부 planned.

결정 사항

  • 2026-07-24: D1 access token 만 browser 로 handoff, browser 가 RS 를 직접 호출(proxy 없음) / 이유: TMB 정의(backend 가 획득하되 access 를 앱에 위임) — BFF 대비 경량 / 대안: BFF(AP3, 모든 API proxy·browser 토큰 0개) 또는 browser-client(AP1, browser 가 OAuth 전담) / 근거: [[raw/official-docs/oauth2-browser-based-apps-ietf-draft]]
  • 2026-07-24: D2 refresh token 은 browser 로 가는 response 에 포함하지 않음(backend 만 보유) / 이유: refresh 노출 시 XSS 1건=장기 세션 탈취, TMB 는 browser-client 보다 안전한 지점이 바로 이것 / 대안: browser 에 refresh 도 전달(browser-client 로 강등) / 근거: [[raw/official-docs/oauth2-browser-based-apps-ietf-draft]](OAUTH-BBA-C1·C2 대비)
  • 2026-07-24: D3(상속 DEC-…-ACCEPTANCE-001@1) 완료 판정 = browser /api 200 AND refresh 가 network 에 부재 / 본 branch 적용점: 두 조건 동시 충족만 done

Decision Evidence Map / 결정-근거 매핑

official-standard(IETF draft) 우선, company-case-study(Curity)는 보조(단독 official 단언 금지). IETF 는 일반 패턴 정의 → project 매핑은 Open Risk.

Decision ID Decision 선택 조건 (언제 이 결정 / 언제 대안) Supporting Claims Evidence Strength Open Risk
D1 access token 만 browser 로 handoff, browser 가 RS 직접 호출(proxy 없음) TMB(AP2) → 이 결정 / BFF(AP3, 전 요청 proxy) 또는 browser-client(AP1) → 대안 raw/official-docs/oauth2-browser-based-apps-ietf-draft.md#OAUTH-BBA-C2, #OAUTH-BBA-C5 official-standard draft 는 "access 를 앱에 제공"만 서술 — handoff 메커니즘(응답 바디 JSON / readable cookie / 전용 엔드포인트)은 규정 안 함 → 구현 결정
D2 refresh token 을 browser response 에 미포함(backend 만 보유) TMB(refresh 서버측) → 이 결정 / browser-client(refresh 브라우저) → 대안 raw/official-docs/oauth2-browser-based-apps-ietf-draft.md#OAUTH-BBA-C1, #OAUTH-BBA-C2, raw/company-tech-blogs/curity-bff-pattern-spa.md#CURITY-BFF-C6, [[raw/branch-notes/feature-keycloak-token-mediating-confidential-client]] D2 official-standard + company-case-study(보조) draft 는 refresh 부재를 직접 문장화하지 않고 "access 만 제공"에서 함의 — refresh 부재 보장 방법(응답에서 제외)은 구현 결정. refresh 노출의 why(탈취 시 유효기간 내내 데이터 접근)는 CURITY-BFF-C6 이 pin(company-case-study 보조 — 단독 official 단언 불가)
D3 완료 판정 = browser /api 200 AND refresh network 부재 (상속 acceptance) 항상 / N/A raw/project-notes/keycloak-patterns-overview.md (DEC-KEYCLOAK-PATTERNS-OVERVIEW-ACCEPTANCE-001@1, 상속) project-decision(inherited) "network 부재"의 검사 범위(응답 바디만 vs 헤더·쿠키 포함)를 명시적으로 정의해야 함

구현 가이드

Trace: D1(OAUTH-BBA-C2/C5) + D2(OAUTH-BBA-C1/C2 + WI-008 D2) + D3(inherited acceptance). AP2 코드 부재(NO_GROUND_TRUTH)라 사전 명세이며 등급 planned.

  • UNSUPPORTED_IMPL_DECISION: (a) handoff 메커니즘 — backend 가 access 를 browser 에 전달하는 방식(로그인 후 backend 엔드포인트가 access 를 JSON 으로 반환 / JS-readable 쿠키 / postMessage 등). IETF draft 는 "제공한다"만 서술, 방식 미규정. trade-off: JSON 반환은 단순하나 access 를 JS 가 읽어 XSS 노출면 존재(TMB 의 알려진 한계), readable cookie 도 유사. 근거 없음 → 착수 시 결정. (b) refresh 부재 검사 범위 — 응답 바디만 vs 헤더/Set-Cookie 전수. trade-off: 바디-only 는 간단하나 Set-Cookie 경유 누출을 놓침 / 전수는 안전(누출 지점 전부 커버)하나 검사 비용↑. 본 branch 는 전수 검사로 수렴(아래 refresh 격리 row · §Claims To Verify 와 정합) — 잔여 미결 아님.
항목 사전 명세 (planned) Trace
Handoff endpoint 로그인 완료 후 backend 가 access token(만)을 browser 에 반환하는 경로 D1 · UNSUPPORTED_IMPL_DECISION(a)
Browser→RS browser 가 받은 access 로 Authorization: Bearer 붙여 RS /api 직접 호출 200 D1(OAUTH-BBA-C2)
refresh 격리 handoff 응답(바디·헤더·쿠키)에서 refresh 제외 — refresh 는 WI-008 서버측 보관에만 존재 D2 · UNSUPPORTED_IMPL_DECISION(b)

엣지·실패·의존

  • 실패·엣지 경로:
    • browser 의 access token 만료 → browser 가 backend handoff 엔드포인트에서 재수령(backend 가 WI-008 D2 로 자동 refresh 후 새 access 발급). refresh 자체 만료 시 재로그인.
    • handoff 응답에 refresh 가 실수로 포함 → 완료조건 위반(D3). 검증 대상.
  • 다른 계약 의존:
    • WI-KEYCLOAK-PATTERNS-OVERVIEW-008(feature-keycloak-token-mediating-confidential-client) D1·D2 — 서버측 토큰 획득·보관을 consume. 그 계약이 바뀌면(저장소·refresh 정책) 본 branch handoff 영향. 특히 handoff 엔드포인트가 browser 를 인증하는 방식(세션 쿠키 vs 기타)은 WI-008 의 세션모델(oauth2Login() 세션 vs 수동 grant — WI-008 §구현 가이드 UNSUPPORTED_IMPL_DECISION(a))에 커플링. WI-008 이 그 축을 정하면 본 branch handoff 인증도 결정된다.
    • WI-KEYCLOAK-PATTERNS-OVERVIEW-004(feature-keycloak-spring-rs-audience-validator) D1·D6 — browser→RS 200 이 소비하는 Resource Server 의 baseline JWT 검증(issuer-uri/JWKS discovery = D6, signature·iss·exp·aud = D1)을 consume. AP2 가 이 AP1 RS 를 재사용하는지 AP2 backend 가 RS 를 겸직하는지는 착수 시 결정(planned). AP2 done-bar(D3)의 signature 함정은 refresh-부재 축이라 aud 검증은 본 branch 완료조건에 비필수(RS 소유 브랜치의 관심사).

검증해야 할 주장 / Claims To Verify

IETF draft 는 패턴 정의(메커니즘 근거)지만 본 프로젝트 실제 동작을 자동 보장하지 않는다. AP2 코드 미구현이라 전부 구현 후 검증.

Claim Why uncertain How to verify Status
browser 가 backend 로부터 access token(만) 수령 handoff 메커니즘 미결(UNSUPPORTED_IMPL_DECISION a) 로그인 후 handoff 응답에 access 존재 + refresh 부재 확인 planned
browser 가 그 access 로 RS /api 200(직접 호출) AP2 코드 미구현 네트워크 탭에서 browser→RS 직접 요청 + 200 확인 planned
refresh token 이 browser 로 가는 network response 에 부재 부재 보장 방법(응답 제외) 미구현 · 검사 범위 미정(b) 네트워크 탭 응답 바디·헤더·Set-Cookie 전수 검사에서 refresh 부재 확인 planned

관심사 커버리지 (coverage-auditor 자동 생성 — 있을 때)

/coverage 실행 전.

마주친 문제

아직 없음.

묶음 (이 branch에서 파생된 자료)

관련 일일 노트

해당 없음.

완료 후 정리

  • PR 링크:
  • 리뷰 메모: