docs(keycloak-session-store): import the session-storage lab as a new project
The keycloak project ended with four open questions that design could not
settle. A two-VM lab was built to answer them by measurement, and this is
that material: 26 experiments, 125 raw command outputs, 22 browser captures.
Follows the import procedure in README.md.
source/ the originating repository verbatim — 78 documents, 28 SVGs,
8 manifests, plus .source-revision recording the commit
final/ the SSOT
document.md 729 lines written from the 29 experiment documents, not
concatenated: what was predicted, what was measured, and
where the measurement itself was wrong
evidence/raw 125 outputs, flattened to <experiment>__<file> because
the originals collided (01-baseline.txt appeared three
times) and the audit only globs the top level
evidence/meta one per raw file; command and exitCode are null and the
README says why rather than inventing them
evidence/browser 22 captures
assets/ three diagrams through techviz
.techviz/ their VizSpecs
A separate project rather than an addition to keycloak: the B-layer answers
that project's four questions, but the A, C and D layers are about cluster
failure, SSO and operations, and one document.md should hold one subject.
The four question records there can point here through 관계.
Recorded rather than papered over: only three of the 28 diagrams were
remade. The repository forbids hand-drawn SVG and forbids titles inside the
canvas; all 28 originals carry both, so converting them is redrawing, not
reformatting. They stay in source/ and the gap is written into the document.
verify-pipeline.py passes. audit-records.py reports no issues.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
43bccd08a8
commit
b2963105a8
+10
-9
@@ -3,7 +3,8 @@ id: 488ce49b-afa4-42a5-a2ce-de2e0653cd82
|
||||
kind: CASE
|
||||
slug: split-custody-access-token
|
||||
title: Refresh Token 관리만 서버로 이전, Access Token은 여전히 Browser에 노출
|
||||
topic: OAuth/OIDC 인증 경계
|
||||
topic: oauth-oidc-auth-boundary
|
||||
topicName: OAuth/OIDC 인증 경계
|
||||
project: KeyCloak Patterns
|
||||
status: 게시 중
|
||||
version: 22
|
||||
@@ -34,11 +35,11 @@ confidential client인 mediator가 code를 교환하고 refresh token을 server-
|
||||
|
||||
## 문제
|
||||
|
||||
Mediator에서는 Spring mediator가 confidential client가 되어 code를 교환하고 access token과 refresh token을 server-side authorized-client service에 저장한다. 브라우저에는 HttpOnly `AP2_SESSION`만 관리하게 된다.
|
||||
Mediator에서는 Spring mediator가 confidential client가 되어 code를 교환하고 access token과 refresh token을 server-side authorized-client service에 저장한다. 브라우저에는 HttpOnly AP2_SESSION만 관리하게 된다.
|
||||
|
||||
서버에서 token을 보관한다는 점만 보면 BFF와 비슷하다. 하지만 Mediator에서는 브라우저가 Resource Server를 직접 호출한다. Resource Server를 호출하려면 access token이 필요하기 때문에 mediator가 access token을 응답으로 다시 반환한다.
|
||||
|
||||
처음에는 refresh token을 서버로 옮기면 브라우저가 credential을 직접 다뤄야 하는 범위도 대부분 줄어든다고 봤다. `/token/access` 응답부터 Resource Server 요청까지 따라가 보니 refresh token은 서버에 남지만 access token은 계속 브라우저에서 사용되고 있었다.
|
||||
처음에는 refresh token을 서버로 옮기면 브라우저가 credential을 직접 다뤄야 하는 범위도 대부분 줄어든다고 봤다. /token/access 응답부터 Resource Server 요청까지 따라가 보니 refresh token은 서버에 남지만 access token은 계속 브라우저에서 사용되고 있었다.
|
||||
|
||||
## 결론
|
||||
|
||||
@@ -79,25 +80,25 @@ HTTP : o
|
||||
|
||||
## 재현 조건
|
||||
|
||||
1. Mediator UI에서 로그인한 뒤 `/token/boundary`를 호출한다.
|
||||
1. Mediator UI에서 로그인한 뒤 /token/boundary를 호출한다.
|
||||
|
||||
accessTokenStored : true
|
||||
refreshTokenStored : true
|
||||
browserReceivesRefreshToken : false
|
||||
|
||||
2. `/token/access` 응답에 다음 세 key만 있는지 확인한다.
|
||||
2. /token/access 응답에 다음 세 key만 있는지 확인한다.
|
||||
|
||||
access_token, token_type, expires_at
|
||||
|
||||
3. 같은 응답의 `Cache-Control`에 `no-store`가 있는지 확인한다.
|
||||
3. 같은 응답의 Cache-Control에 no-store가 있는지 확인한다.
|
||||
|
||||
4. 반환된 access JWT를 decode해 audience에 `keycloak-pattern-api`가 있는지 확인한다.
|
||||
4. 반환된 access JWT를 decode해 audience에 keycloak-pattern-api가 있는지 확인한다.
|
||||
|
||||
5. 브라우저가 해당 token으로 Resource Server를 직접 호출했을 때 200을 받는지 확인한다.
|
||||
|
||||
6. cookie가 `AP2_SESSION`이며 HttpOnly와 SameSite=Lax인지 확인한다.
|
||||
6. cookie가 AP2_SESSION이며 HttpOnly와 SameSite=Lax인지 확인한다.
|
||||
|
||||
7. Local Storage와 Session Storage에 access token 원문이나 `refresh_token` 문자열이 없는지 확인한다.
|
||||
7. Local Storage와 Session Storage에 access token 원문이나 refresh_token 문자열이 없는지 확인한다.
|
||||
|
||||
## 본문
|
||||
|
||||
|
||||
Reference in New Issue
Block a user