1
0
forked from baron/baron-sso

feat(headless-login): add jwks cache visibility and refresh flow

- replace inline headless jwks support with jwksUri-only validation
- add cached jwks refresh worker, manual refresh/revoke endpoints, and parsed key summaries
- expose allowed algorithms and key previews in DevFront with regression coverage
This commit is contained in:
Lectom C Han
2026-04-01 18:33:22 +09:00
parent f51cdba51a
commit 9facd24a00
20 changed files with 2393 additions and 499 deletions

View File

@@ -143,19 +143,52 @@ flowchart
- Hydra login request의 `client.client_id`와 요청 바디의 `client_id`가 반드시 같아야 합니다.
- client가 headless login 선행 조건을 만족해야 합니다.
- `headless_token_endpoint_auth_method == "private_key_jwt"` 또는 top-level `token_endpoint_auth_method == "private_key_jwt"`
- `headless_jwks_uri` 또는 `headless_jwks`가 존재해야 합니다.
- `headless_jwks_uri`가 존재해야 합니다.
- inline `headless_jwks`는 더 이상 지원하지 않습니다.
- `headless_login_enabled == true`가 필요합니다.
- `metadata.status == "inactive"`인 client는 차단됩니다.
#### `client_assertion` 규칙
- 구현상 `client_assertion`은 현재 필수입니다.
- 허용 서명 알고리즘:
- `RS256`, `RS384`, `RS512`
- `PS256`, `PS384`, `PS512`
- `ES256`, `ES384`, `ES512`
- `EdDSA`
- JWT claim의 `iss``sub`는 모두 `client_id`와 같아야 합니다.
- `exp`는 현재 시각 이후여야 합니다.
- `nbf`, `iat`가 있으면 미래 시각이면 안 됩니다.
- `aud`는 다음 둘 중 하나와 일치해야 합니다.
- `https://<backend-origin>/api/v1/auth/headless/password/login`
- `/api/v1/auth/headless/password/login`
- 서명 검증용 public key는 `headless_jwks_uri` 또는 `headless_jwks`에서 읽습니다.
- 서명 검증용 public key는 `headless_jwks_uri`에서 읽습니다.
#### 내부 JWKS 캐시 정책
- Baron Backend는 `headless_jwks_uri`를 직접 외부 스펙으로 저장하고, 실제 JWKS 문서는 내부 캐시에 저장해 사용합니다.
- 등록/수정 이후에는 내부 캐시 동기화를 시도하고, 성공/실패 상태를 DevFront에서 확인할 수 있습니다.
- 로그인 시 재조회는 다음 조건으로 제한합니다.
- 캐시에 `kid`가 없을 때
- `kid`는 있지만 서명 검증이 실패할 때
- 캐시 TTL이 만료되었을 때
- 그 외에는 내부 캐시를 사용합니다.
- 백그라운드 worker가 TTL보다 짧은 주기로 `jwksUri`를 선제 점검해 첫 사용자 실패를 줄입니다.
#### DevFront 운영 액션
- Settings > `Public Key Registration` 카드에서 다음 정보를 확인할 수 있습니다.
- 최근 JWKS 캐시 갱신 시각
- 최근 검증 성공 시각
- 최근 에러와 연속 실패 횟수
- 현재 cached `kid` 목록
- 파싱된 key summary
- `kid`
- `kty`
- `use`
- `alg`
- RSA key의 `n` preview (앞/뒤 일부만 표시)
- 수동 운영 액션:
- `Refresh JWKS Cache`
- `Revoke JWKS Cache`
- RP가 키를 교체했으면 실제 트래픽 전에 `Refresh JWKS Cache`를 먼저 호출하는 것을 권장합니다.
#### 일반 로그인과의 차이
- `POST /api/v1/auth/password/login`
@@ -172,9 +205,13 @@ flowchart
- 필수 필드 누락
- `client_assertion` 누락
- `401 invalid_client_assertion`
- JWKS 조회 실패
- `jwksUri` 조회 실패
- 서명 불일치
- `aud`/`iss`/`sub`/`exp` 검증 실패
- `401 invalid_client_assertion` with explicit message
- `Headless login requires jwksUri. Inline jwks is not supported.`
- `Configured jwksUri returned no keys for headless login.`
- `Failed to refresh headless login jwks from jwksUri.`
- `403 forbidden`
- `client_id` 불일치
- `headless_login_enabled` 미설정