Phase 19: Local Auth (No-OIDC Mode) #23

Merged
luckberg merged 78 commits from gsd/phase-19-local-auth-no-oidc-mode into main 2026-06-18 06:25:00 -04:00
Showing only changes of commit 3674b255b2 - Show all commits
+27 -1
View File
@@ -114,10 +114,36 @@ export function devSessionCookieMiddleware(): MiddlewareHandler {
// LOCAL_SESSION_SECRET not set — bypass mode exempts the secret requirement
// (assertLocalSessionSecretSet skips when DEV_AUTH_BYPASS=true), but we cannot
// issue a cookie without it. Degrade gracefully so devAuthBypass still works.
if (!process.env.LOCAL_SESSION_SECRET) {
const secret = process.env.LOCAL_SESSION_SECRET;
if (!secret) {
return async (_c, next) => next();
}
// BL-01: do not treat "present" as "safe". The boot guard's length floor
// (assertLocalSessionSecretSet, >= 32 chars) is SKIPPED in bypass mode, so apply the
// same floor here before minting a real, signature-valid local-session JWT for DEV_USER
// (id=1). A short/forgeable secret must NOT issue a genuine session token. Degrade to a
// no-op so the cookie is never signed with a weak key.
if (secret.length < 32) {
console.warn(
'[devSessionCookieMiddleware] LOCAL_SESSION_SECRET is shorter than 32 characters — ' +
'refusing to issue a dev local-session cookie. Generate a strong value with ' +
'node scripts/generate-secrets.mjs.',
);
return async (_c, next) => next();
}
// BL-01: warn loudly if the secret is the well-known dev placeholder. A genuine,
// signature-valid session token minted under this known value is trivially forgeable
// if the same secret ever leaks into a non-bypass environment.
if (secret === 'dev-secret-change-me-0000000000000000') {
console.warn(
'[devSessionCookieMiddleware] LOCAL_SESSION_SECRET is the well-known dev placeholder. ' +
'This is acceptable ONLY for local dev/CI under DEV_AUTH_BYPASS — never reuse this ' +
'value in any non-bypass or shared environment.',
);
}
// Bypass active + secret set: issue a real local-session cookie for DEV_USER
// on each request that does not already carry one.
return async (c, next) => {