feat(19-01): implement localSession JWT cookie helpers and assertLocalSessionSecretSet boot guard
- localSession.ts: issueLocalSessionCookie/verifyLocalSessionCookie/clearLocalSessionCookie - Jwt namespace import from hono/utils/jwt (Pitfall 8 — not named sign/verify) - Cookie name: 'local-session' (distinct from 'oidc-auth', Pitfall 4) - httpOnly, sameSite=Lax, secure in production; try/catch on Jwt.verify (Pitfall 9) - verifyLocalSessionCookie returns null (never throws) on any error - bootGuards.ts: assertLocalSessionSecretSet — exit(1) if secret missing/<32 chars - Exempt when DEV_AUTH_BYPASS=true (bypass doesn't issue local-session cookies) - index.ts: wire assertLocalSessionSecretSet() after assertNotDevBypassInProduction() - All 5 unit tests pass; typecheck exits 0
This commit is contained in:
@@ -32,3 +32,35 @@ export function assertNotDevBypassInProduction(): void {
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refuses to start the process when LOCAL_SESSION_SECRET is absent or shorter
|
||||
* than 32 characters, UNLESS dev-bypass mode is active.
|
||||
*
|
||||
* Rationale (D-05 / T-19-03 / Pitfall 10):
|
||||
* LOCAL_SESSION_SECRET signs the local-session JWT cookie. A missing or weak
|
||||
* secret means any issued session cookie can be trivially forged. This boot
|
||||
* guard converts a silent misconfiguration into an immediate loud failure
|
||||
* instead of letting the API start and issue insecure JWTs.
|
||||
*
|
||||
* DEV_AUTH_BYPASS=true is exempt: bypass mode never issues local-session cookies
|
||||
* (the OIDC/dev-bypass path handles auth), so the secret is not required there.
|
||||
* This mirrors assertNotDevBypassInProduction's exempt logic.
|
||||
*
|
||||
* Call immediately after assertNotDevBypassInProduction() in the isMainModule()
|
||||
* boot block in index.ts.
|
||||
*/
|
||||
export function assertLocalSessionSecretSet(): void {
|
||||
// Exempt when dev-bypass is active — bypass mode doesn't issue local-session JWTs
|
||||
if (process.env.DEV_AUTH_BYPASS === 'true') return;
|
||||
|
||||
const secret = process.env.LOCAL_SESSION_SECRET;
|
||||
if (!secret || secret.length < 32) {
|
||||
console.error(
|
||||
'[FATAL] LOCAL_SESSION_SECRET is not set or is shorter than 32 characters. ' +
|
||||
'This secret signs local-session JWT cookies. Refusing to start. ' +
|
||||
'Run: node scripts/generate-secrets.mjs to generate a value.',
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user