feat(19-03): implement localAuthMiddleware, GET /api/auth/mode, and pre-auth route mounts
- localAuthMiddleware: cookie→c.set('user') with Pitfall-1 guard (no-set on no-cookie path)
- authMode: GET /api/auth/mode pre-auth endpoint (localEnabled:true, oidcEnabled from env+config)
- localAuth: POST /api/auth/local/login (rate-limit + timing-safe), logout routes
- index.ts: mount authModeRouter + localAuthRouter pre-auth; localAuthMiddleware after devAuthBypass; OIDC guard wrapped skip-when-user-set
This commit is contained in:
+25
-2
@@ -11,12 +11,15 @@ import { listsRouter, listItemsRouter } from './routes/lists.js';
|
||||
import { pushRouter } from './routes/push.js';
|
||||
import { adminRouter } from './routes/admin.js';
|
||||
import { setupRouter } from './routes/setup.js';
|
||||
import { authModeRouter } from './routes/authMode.js';
|
||||
import { localAuthRouter } from './routes/localAuth.js';
|
||||
import {
|
||||
oidcAuthMiddleware,
|
||||
processOAuthCallback,
|
||||
oidcConfigFallbackMiddleware,
|
||||
} from './auth/middleware.js';
|
||||
import { devAuthBypass } from './auth/devBypass.js';
|
||||
import { localAuthMiddleware } from './auth/localAuthMiddleware.js';
|
||||
import { persistSessionCookie } from './auth/persistSessionCookie.js';
|
||||
import { startBrokerPoller } from './broker/poller.js';
|
||||
import { startOutboxWorker, initOutboxTrigger } from './broker/outboxWorker.js';
|
||||
@@ -48,15 +51,26 @@ app.route('/health', healthRouter);
|
||||
// 423 lock after setup is complete (SETUP-04 / D-10).
|
||||
app.route('/api/setup', setupRouter);
|
||||
|
||||
// Phase 19 — pre-auth auth routes: GET /api/auth/mode and POST /api/auth/local/login, /logout.
|
||||
// Mounted BEFORE devAuthBypass so they are reachable without a session (D-01 / AUTH-LOCAL-05).
|
||||
app.route('/api/auth', authModeRouter);
|
||||
app.route('/api/auth', localAuthRouter);
|
||||
|
||||
// Dev-auth bypass — no-op passthrough unless DEV_AUTH_BYPASS=true AND NODE_ENV!='production'.
|
||||
// When active, injects DEV_USER into the Hono context and the OIDC guard is NOT mounted.
|
||||
// Must be mounted BEFORE oidcAuthMiddleware (T-02-01 mitigation; see auth/devBypass.ts).
|
||||
app.use('/api/*', devAuthBypass());
|
||||
|
||||
// Phase 19 — local-session middleware: sets c.get('user') from 'local-session' JWT cookie.
|
||||
// No-op passthrough when no cookie is present — the OIDC guard fires for unauthenticated.
|
||||
// Runs AFTER devAuthBypass (which may set c.get('user') first) and BEFORE the OIDC guard.
|
||||
// The OIDC guard below is wrapped to skip when c.get('user') is already set (Pitfall 1 guard).
|
||||
app.use('/api/*', localAuthMiddleware());
|
||||
|
||||
// Protect all /api/* routes with OIDC session middleware (AUTH-01, T-02-05).
|
||||
// Skipped entirely when devBypassActive so that local dev works without Authelia.
|
||||
// In production devBypassActive is always false — OIDC is unconditionally mounted.
|
||||
// Unauthenticated requests receive a 302 redirect to Authelia's authorize endpoint.
|
||||
// Unauthenticated requests receive a 302 redirect to the OIDC authorize endpoint.
|
||||
// OIDC_AUTH_EXTERNAL_URL is MANDATORY behind Pangolin to construct the correct
|
||||
// redirect_uri (Pitfall 1). Set it to https://familysync.<domain>.
|
||||
if (!devBypassActive) {
|
||||
@@ -67,7 +81,16 @@ if (!devBypassActive) {
|
||||
// A2 CONFIRMED: oidcAuthMiddleware() reads process.env per-request (call time), so
|
||||
// injecting into process.env here is safe and effective (see auth/middleware.ts A2 note).
|
||||
app.use('/api/*', oidcConfigFallbackMiddleware);
|
||||
app.use('/api/*', oidcAuthMiddleware());
|
||||
// Phase 19 / D-03: OIDC guard wrapped to skip when c.get('user') is already set.
|
||||
// A valid local-session (or dev-bypass) user must NOT be 302-redirected to the OIDC
|
||||
// provider — the skip-when-set wrapper is the coexistence seam (D-03 / RESEARCH Pitfall 1).
|
||||
app.use('/api/*', async (c, next) => {
|
||||
if (c.get('user')) {
|
||||
await next();
|
||||
return;
|
||||
}
|
||||
await oidcAuthMiddleware()(c, next);
|
||||
});
|
||||
// Re-issues the session-scoped oidc-auth cookie as persistent so PWA sessions survive close (AUTH-02).
|
||||
app.use('/api/*', persistSessionCookie());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user