KeiSeiKit-1.0/skills/auth-setup/phase-3-session-strategy.md
Parfii-bot 0be354a920 KeiSeiKit-public — clean state
Single-commit clean baseline after security scrub of niche-tells,
project codenames, internal jargon, and contributor-email leaks.

Contents:
- 100 Rust crates (_primitives/_rust/)
- 37 agent manifests (_manifests/) + generated specs (_generated/)
- 67 user-invocable skills (skills/)
- 33 hooks (hooks/)
- Composition blocks (_blocks/)
- Documentation (docs/, README.md)
- TS adapter packages (_ts_packages/)
- Assembler (_assembler/)
- Roles (_roles/)
- Templates (_templates/)
- Forgejo CI (.forgejo/)

Author: Denis Parfionovich <info@greendragon.info>

License: see LICENSE.
2026-05-01 12:09:03 +08:00

79 lines
3.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Phase 3 — Session strategy + cookie configuration
Decides how the authenticated principal is carried across requests. Reads
`_blocks/auth-sessions.md` heavily. Default bias: server-side opaque
sessions (revocable, simple) unless the user needs horizontal stateless
scale.
## 3a — Strategy click (AskUserQuestion, single-select)
```json
{
"questions": [
{
"question": "Session carrier?",
"header": "Session",
"multiSelect": false,
"options": [
{"label": "Server-side session + cookie (DEFAULT)",
"description": "Opaque 256-bit id in HttpOnly Secure cookie; row in DB/Redis. Instant revoke. Recommended for >95% of apps."},
{"label": "JWT access + opaque refresh",
"description": "ES256 access ≤15 min in HttpOnly cookie; refresh rotated server-side. Use ONLY when you have stateless edge workers that can't reach the session DB."},
{"label": "JWT access + refresh in native secure storage",
"description": "Mobile app; refresh in Keychain / Keystore. Same rotation rules; cookie flags N/A."},
{"label": "Managed (Clerk / Supabase / Auth0)",
"description": "Provider owns the session primitive; skill records the SDK integration points only."}
]
}
]
}
```
Store as `SESSION`.
## 3b — Emit cookie-flag checklist (inline, no AskUserQuestion)
Apply ONLY when `SESSION` involves a browser cookie. For every cookie the
app sets (session, CSRF, anti-re-use nonce):
```
[ ] HttpOnly — blocks JS read; XSS-resistant
[ ] Secure — HTTPS only; reject on cleartext
[ ] SameSite=Lax — default; use Strict for cross-site-hostile apps
[ ] __Host- prefix — no Domain, Path=/, Secure — session cookie only
[ ] Max-Age tuned — 730 d sliding (consumer) / 24 h hard (regulated)
[ ] Rotation on login, — new session_id issued, old row deleted or revoked_at set
logout-all, passkey/password change, privilege elevation
[ ] Logout deletes BOTH — server row AND cookie (Max-Age=0, same flags)
```
## 3c — Emit JWT-specific checklist (inline) — only if JWT chosen
```
[ ] Algorithm = ES256 — asymmetric; NOT HS256 for cross-service
[ ] access_token ≤15 min — minimises revocation-gap window
[ ] refresh_token OPAQUE — stored server-side, rotated on every use
[ ] refresh-reuse detection — family revocation on stolen refresh
[ ] JWKS rotation + kid — key rollover without service restart
[ ] Claims validated — iss, aud, exp, nbf, iat, sub, nonce (if OIDC)
[ ] NEVER in localStorage — HttpOnly cookie (web) / secure storage (native)
[ ] Logout policy stated — "revoke refresh only; access valid until exp"
and accepted by the product (or escalate to server-session strategy)
```
## 3d — CSRF strategy (inline, driven by SESSION)
- Cookie session + same-origin forms → `SameSite=Lax` is enough; plus a
CSRF token (cookie+header double-submit) for cross-origin POSTs.
- Cookie session + third-party embed (iframes, extensions) → `SameSite=None;
Secure` + mandatory CSRF token, reject missing/mismatched.
- Bearer-token API (no cookie) → no CSRF (no ambient credential); enforce
`Origin` header check as defence-in-depth.
## Verify-criterion
- `SESSION` set to exactly one strategy.
- At least one of the three checklists (3b / 3c / 3d) applies and was
emitted.
- If JWT chosen, 3c is printed in full AND the logout gap was explicitly
acknowledged in the report.