90 lines
3.3 KiB
Markdown
90 lines
3.3 KiB
Markdown
---
|
|
phase: 260610-k1z
|
|
plan: 01
|
|
subsystem: auth
|
|
tags: [oidc, session, cookie, pwa, persistence]
|
|
dependency_graph:
|
|
requires: [@hono/oidc-auth oidcAuthJwt context var]
|
|
provides: [persistSessionCookie middleware, AUTH-02]
|
|
affects: [apps/api/src/index.ts]
|
|
tech_stack:
|
|
added: []
|
|
patterns: [hono-middleware, cookie-upgrade]
|
|
key_files:
|
|
created:
|
|
- apps/api/src/auth/persistSessionCookie.ts
|
|
- apps/api/tests/auth/persistSessionCookie.test.ts
|
|
modified:
|
|
- apps/api/src/index.ts
|
|
decisions:
|
|
- "Set-before-next ordering: cookie re-issued before await next() so any future downstream logout/delete wins as the last Set-Cookie"
|
|
- "Guard on c.get('oidcAuthJwt'): falsy path does nothing — no resurrection of deleted/absent cookies"
|
|
- "Conditional domain: domain key absent (not undefined) when OIDC_COOKIE_DOMAIN unset — mirrors library logic"
|
|
metrics:
|
|
duration: ~5m
|
|
completed: "2026-06-10T18:32:47Z"
|
|
tasks_completed: 2
|
|
files_changed: 3
|
|
---
|
|
|
|
# Phase 260610-k1z Plan 01: Persist OIDC Session Cookie with Max-Age Summary
|
|
|
|
**One-liner:** Hono middleware that upgrades the session-scoped oidc-auth cookie (no maxAge) set by @hono/oidc-auth to a persistent cookie with Max-Age, SameSite=Lax, guarded to never resurrect absent/deleted cookies.
|
|
|
|
## What Was Built
|
|
|
|
`persistSessionCookie()` is a thin Hono `MiddlewareHandler` mounted immediately after `oidcAuthMiddleware()` in `index.ts` (inside the `!devBypassActive` block). It reads `c.get('oidcAuthJwt')` — a context key set by @hono/oidc-auth only on requests where a valid session was created or refreshed — and re-issues the same signed JWT as a persistent Set-Cookie (adding `Max-Age` + `SameSite=Lax`). When `oidcAuthJwt` is falsy (logged-out, no session, unauthenticated), it is a pure passthrough: no cookie is emitted.
|
|
|
|
## Tasks Completed
|
|
|
|
| Task | Name | Commit | Files |
|
|
|------|------|--------|-------|
|
|
| 1 | Create persistSessionCookie() middleware | aabcb5d | apps/api/src/auth/persistSessionCookie.ts |
|
|
| 2 | Wire into index.ts + unit tests | 8343fad | apps/api/src/index.ts, apps/api/tests/auth/persistSessionCookie.test.ts |
|
|
|
|
## Verification Results
|
|
|
|
### typecheck
|
|
```
|
|
$ pnpm --filter @familysync/api typecheck
|
|
$ tsc --noEmit
|
|
(exit 0 — no output)
|
|
```
|
|
|
|
### vitest run tests/auth/
|
|
```
|
|
RUN v4.1.8 /home/luc/Projects/familysync/apps/api
|
|
|
|
Test Files 3 passed (3)
|
|
Tests 14 passed (14)
|
|
Start at 14:32:33
|
|
Duration 2.45s (transform 162ms, setup 1.74s, import 142ms, tests 152ms, environment 0ms)
|
|
```
|
|
|
|
All 3 auth test files pass (devBypass, user, persistSessionCookie). 14/14 tests green including:
|
|
- Test A (persist path): truthy oidcAuthJwt → Set-Cookie with Max-Age, SameSite=Lax, HttpOnly, Secure
|
|
- Test B (guard path): absent oidcAuthJwt → no oidc-auth Set-Cookie emitted
|
|
- Guard variant: empty string oidcAuthJwt → no resurrection
|
|
|
|
## Deviations from Plan
|
|
|
|
None — plan executed exactly as written.
|
|
|
|
## Known Stubs
|
|
|
|
None.
|
|
|
|
## Threat Flags
|
|
|
|
None. The new middleware only re-issues a cookie that @hono/oidc-auth already set; it does not open new network endpoints or auth paths.
|
|
|
|
## Self-Check: PASSED
|
|
|
|
- [x] apps/api/src/auth/persistSessionCookie.ts exists
|
|
- [x] apps/api/tests/auth/persistSessionCookie.test.ts exists
|
|
- [x] apps/api/src/index.ts contains `persistSessionCookie()`
|
|
- [x] Commit aabcb5d exists
|
|
- [x] Commit 8343fad exists
|
|
- [x] typecheck exits 0
|
|
- [x] vitest tests/auth/ all pass
|