From 7056e012a7c51eab4405d2e380f44f20e885170e Mon Sep 17 00:00:00 2001 From: gitea-impl-agent Date: Fri, 2 Oct 2026 04:48:06 +0000 Subject: [PATCH] docs(auth): complete persistent token contracts --- docs/interface-contract.md | 7 ++++++- docs/runtime-flow.md | 10 ++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/docs/interface-contract.md b/docs/interface-contract.md index a1dfb0f..e47679a 100644 --- a/docs/interface-contract.md +++ b/docs/interface-contract.md @@ -66,6 +66,8 @@ Dashboard 인증 설정, login/cleanup/logout HTTP route, signed cookie와 Strea | `Set-Cookie` | response header | `cookie` | success | hardened auth cookie, redacted value | persistent auth | 값은 민감 | | `Location` | response header | `string` | success/failure | `/` or generic error path | browser navigation | 비민감 | +발급 token은 `v`, `sub=dashboard-admin`, `iat`, `exp`, `jti` claim만 가진다. `sub=dashboard-admin`은 관리자 ID가 아닌 고정 비민감 role이고, token 값과 서명은 민감하므로 browser의 hardened cookie에만 저장한다. 성공한 login 시각에 `iat`와 `exp`를 한 번 고정하며 기본 TTL은 24시간, `remember_me=on`이면 30일이다. 활동, 일반 요청, rerun 또는 인증 복원은 token을 재발급하거나 두 시각을 연장하지 않는다. + #### 오류 | 코드 | 분류 | 발생 조건 | 재시도 가능 여부 | 호출자 대응 | 실패 시 상태 변경 | @@ -148,7 +150,7 @@ Dashboard 인증 설정, login/cleanup/logout HTTP route, signed cookie와 Strea | 필드 | 위치 | 타입 | 필수 여부 | 기본값 | 허용 값·형식 | 의미 | 민감정보 | |---|---|---|---|---|---|---|---| -| `auth_cookie` | request cookie | `string` | success path | absent | signed token | browser proof | 민감 | +| `auth_cookie` | request cookie | `string` | success path | absent | current configuration으로 서명을 검증할 수 있고 claim이 정확히 `v`, `sub=dashboard-admin`, `iat`, `exp`, `jti`인 token | browser proof | 값과 서명은 민감; `sub`는 비민감 | #### 출력 @@ -162,6 +164,8 @@ Dashboard 인증 설정, login/cleanup/logout HTTP route, signed cookie와 Strea |---|---|---|---|---|---| | `unauthenticated` | authentication | absent/invalid/expired/config failure | login 가능 | cleanup then show login | no protected work | +관리자 ID, password 또는 signing secret 변경은 server-only signing key binding을 바꾸므로 기존 token을 모두 무효화하고 cleanup으로 전이한다. DB session, token registry와 per-token revocation은 만들지 않는다. + ## 호환성 - 유지할 기존 호출 방식: authenticated `page` query parameter, page dispatch, gateway와 MCP behavior @@ -170,6 +174,7 @@ Dashboard 인증 설정, login/cleanup/logout HTTP route, signed cookie와 Strea - 재시도 계약: credential 실패는 최소 1초 지연; origin/request 오류는 수정 후 재시도 - 중복 처리 계약: login은 새 token 발급 가능; cleanup/logout deletion은 idempotent - 순서 보장: config → cookie verify → cleanup if invalid → DB/page dispatch only if valid +- 만료 보장: login 성공 시 고정한 `iat`와 `exp`는 활동·일반 요청·rerun·복원에서 변경하거나 연장하지 않음 ## 예시 diff --git a/docs/runtime-flow.md b/docs/runtime-flow.md index 11190a9..63f9049 100644 --- a/docs/runtime-flow.md +++ b/docs/runtime-flow.md @@ -36,8 +36,8 @@ ASGI startup부터 login, token restoration, invalid-cookie cleanup, explicit lo | `login-01` | auth server | POST `/api/auth/login` | validate scheme/origin/body | request only | none | `login-02` | `login-reject` | | `login-02` | authentication | validated form | load three settings, fail closed | server memory | secret provider/environment | `login-03` | `config-fail` | | `login-03` | authentication | configured settings | constant-time compare ID/password | no persistent write | none | `login-04` | `login-fail` | -| `login-04` | authentication | valid credential | issue signed claims with `sub=dashboard-admin` | server memory | none | `login-05` | `login-fail` | -| `login-05` | auth server | signed token | set hardened cookie and redirect | browser cookie write | response | `gate-01` | `login-fail` | +| `login-04` | authentication | valid credential | issue exactly `v`, `sub=dashboard-admin`, `iat`, `exp`, `jti`; fix `iat`/`exp` at login success for default 24 hours or `remember_me=on` 30 days | server memory | none | `login-05` | `login-fail` | +| `login-05` | auth server | signed token | set hardened cookie with selected absolute expiry and redirect; later activity never reissues or extends it | browser cookie write | response | `gate-01` | `login-fail` | ### restore — Existing cookie restoration @@ -49,7 +49,7 @@ ASGI startup부터 login, token restoration, invalid-cookie cleanup, explicit lo | 단계 ID | 실행 주체 | 시작 조건·입력 | 처리 | 읽기·쓰기 상태 | 외부 호출 | 성공 시 다음 단계 | 실패 시 전이 | |---|---|---|---|---|---|---|---| | `gate-01` | dashboard app | page startup | call authentication before DB path/page dispatch | no DB access | none | `gate-02` | `unauthenticated` | -| `gate-02` | authentication | current config and cookie | verify signature, exact claims, fixed role subject, TTL and rotation | no session write | none | `dashboard-01` | `cleanup-01` | +| `gate-02` | authentication | current config and cookie | verify signature, exact `v`/`sub=dashboard-admin`/`iat`/`exp`/`jti` claims, current admin-ID/password/signing-secret binding and absolute `exp`; never refresh or extend on restoration, rerun or activity | no session or token write | none | `dashboard-01` | `cleanup-01` | | `dashboard-01` | dashboard app | accepted token | resolve DB path and dispatch requested page | existing SQLite reads/writes | gateway/page code | `authenticated` | `dashboard-fail` | ### cleanup — Invalid cookie cleanup @@ -82,7 +82,7 @@ ASGI startup부터 login, token restoration, invalid-cookie cleanup, explicit lo |---|---|---|---|---|---|---| | `login-02` | missing/empty/read-error/short secret | yes | fix deployment config | no cookie | operator injects secret | `config-fail` | | `login-03` | wrong ID/password | yes | retry after generic error and 1s delay | no lock | external rate limit | `login-fail` | -| `gate-02` | invalid/expired/tampered/claim/rotation failure | yes | cleanup then login | matching deletion | user logs in again | `unauthenticated` | +| `gate-02` | expired, malformed/tampered claims, or admin-ID/password/signing-secret rotation failure | yes | cleanup then login | matching deletion | user logs in again | `unauthenticated` | | `cleanup-02` | non-HTTPS/cross-origin | yes | retry same origin | deletion is idempotent | browser clears manually if needed | `cleanup-reject` | | `logout-02` | non-HTTPS/cross-origin | yes | retry same origin | deletion is idempotent | browser clears manually if needed | `logout-reject` | @@ -92,6 +92,8 @@ ASGI startup부터 login, token restoration, invalid-cookie cleanup, explicit lo - 잠금·직렬화 단위: none for authentication; existing SQLite rules remain for financial writes - 순서 보장: config/cookie gate precedes DB path, gateway and page dispatch - 충돌 검출·처리: token is stateless; password/signing-secret/admin-ID rotation invalidates old claims +- 만료 불변조건: login 성공 시 고정한 `iat`와 `exp`는 복원·rerun·활동 동안 바뀌지 않으며 token을 재발급하거나 만료를 연장하지 않음 +- rotation 불변조건: admin ID, password 또는 signing secret 변경은 이전 설정으로 발급한 모든 token을 무효화하고 `cleanup-01`로 전이 ## 관찰 가능성