feat(ap2): hand off access token only

This commit is contained in:
donghyeon-ka
2026-07-25 14:28:56 +09:00
parent 774f492750
commit bd48516e0f
14 changed files with 402 additions and 8 deletions
+38
View File
@@ -0,0 +1,38 @@
# AP2 · Token-Mediating Backend
## 책임 경계
1. 브라우저는 Spring backend의 `/oauth2/authorization/keycloak`로 로그인을
시작합니다.
2. Keycloak은 authorization code를 Spring callback으로 전달합니다.
3. confidential client인 Spring backend가 client secret을 사용해 code를
교환하고 access/refresh token을 `OAuth2AuthorizedClientService`
보관합니다.
4. 브라우저가 `/token/access`를 호출하면 backend는 현재 access token,
token type, 만료 시각만 `Cache-Control: no-store`로 반환합니다.
5. 브라우저는 전달받은 access token을 메모리에서만 사용해 Resource
Server를 직접 호출합니다.
refresh token은 브라우저 응답, Web Storage, cookie에 전달되지 않습니다.
access token이 만료되면 `OAuth2AuthorizedClientManager`가 서버에 보관된
refresh token으로 갱신한 뒤 새 access token만 전달할 수 있습니다.
## 확인할 보안 속성
- Keycloak client는 `client_secret_basic`을 사용하는 confidential client입니다.
- Resource Server는 서명, issuer, timestamp와 함께
`aud=keycloak-pattern-api`를 검증합니다.
- CORS는 AP2 UI origin인 `http://localhost:8082``GET`만 허용합니다.
- access-token 응답에는 `refresh_token` 필드가 없고 `no-store`가 적용됩니다.
- 브라우저 cookie에는 HttpOnly, SameSite=Lax인 `AP2_SESSION` 식별자만
저장됩니다. 실제 OAuth token은 session cookie 안에 들어가지 않습니다.
## 실행
```bash
./scripts/verify-pattern2.sh
```
검증은 실제 Keycloak 로그인 후 서버 token 보관 여부, access-only 응답의
필드 집합과 audience, 브라우저의 직접 Resource Server 호출, Web Storage
비사용을 확인합니다.