Files
familysync/apps/api/src/routes/authMode.ts
T
Lucas Berger be7a0aec90 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
2026-06-17 16:48:17 -04:00

51 lines
1.8 KiB
TypeScript

/**
* authMode.ts — GET /api/auth/mode pre-auth endpoint (AUTH-LOCAL-05).
*
* Returns { localEnabled: boolean, oidcEnabled: boolean } reflecting the current
* authentication configuration. This endpoint is intentionally reachable before
* authentication (same pre-auth pattern as GET /api/setup/status).
*
* Mount in index.ts BEFORE devAuthBypass and OIDC guard:
* app.route('/api/auth', authModeRouter); ← pre-auth
*
* Response contract:
* - localEnabled: always true — local auth is the default, always available (D-01).
* - oidcEnabled: true when OIDC_ISSUER env var is set, OR when app_config has
* an oidc_issuer row (supports wizard-configured OIDC before container restart).
*
* No auth gate, no isSetupLocked() check — the PWA fetches this on app load before
* knowing if the user is authenticated.
*/
import { Hono } from 'hono';
import { eq } from 'drizzle-orm';
import { db } from '../db/client.js';
import { appConfig } from '../db/schema.js';
export const authModeRouter = new Hono();
/**
* GET / (mounted as /api/auth, so effective path is GET /api/auth/mode)
*
* Checks OIDC_ISSUER env var first (process.env is cheapest); falls back to
* app_config DB row if env var is absent (wizard-configured OIDC).
*/
authModeRouter.get('/mode', async (c) => {
// localEnabled: always true (D-01)
// oidcEnabled: env var first, then app_config fallback
const issuerFromEnv = process.env.OIDC_ISSUER;
let oidcEnabled = Boolean(issuerFromEnv);
if (!oidcEnabled) {
// Check app_config for oidc_issuer (wizard-written, pre-restart-fallback pattern from middleware.ts)
const [row] = await db
.select({ value: appConfig.value })
.from(appConfig)
.where(eq(appConfig.key, 'oidc_issuer'))
.limit(1);
oidcEnabled = Boolean(row?.value);
}
return c.json({ localEnabled: true, oidcEnabled });
});