export interface AuthEnv { OIDC_ISSUER?: string; OIDC_CLIENT_ID?: string; OIDC_CLIENT_SECRET?: string; OIDC_PROVIDER_NAME?: string; AUTH_SECRET?: string; NEXTAUTH_URL?: string; } export interface AuthMode { enabled: boolean; error: string | null; } export interface OidcProfile { sub: unknown; name?: unknown; preferred_username?: unknown; email?: unknown; picture?: unknown; } const REQUIRED_AUTH_KEYS = [ "OIDC_ISSUER", "OIDC_CLIENT_ID", "OIDC_CLIENT_SECRET", "AUTH_SECRET", ] as const; const OIDC_KEYS = [ "OIDC_ISSUER", "OIDC_CLIENT_ID", "OIDC_CLIENT_SECRET", ] as const; const STATIC_FILE_PATTERN = /\.(?:ico|svg|png|jpg|jpeg|gif|webp|css|js|map|txt|xml|json)$/i; export function getAuthMode(env: AuthEnv = process.env): AuthMode { const hasAnyOidcConfig = OIDC_KEYS.some((key) => Boolean(trimEnv(env[key]))); if (!hasAnyOidcConfig) return { enabled: false, error: null }; const missing = REQUIRED_AUTH_KEYS.filter((key) => !trimEnv(env[key])); if (missing.length > 0) { return { enabled: false, error: `Missing required auth environment variables: ${missing.join(", ")}`, }; } return { enabled: true, error: null }; } export function isAuthEnabled(env: AuthEnv = process.env): boolean { return getAuthMode(env).enabled; } export function isAuthRoute(pathname: string): boolean { return pathname === "/api/auth" || pathname.startsWith("/api/auth/"); } export function isProtectedPath(pathname: string): boolean { if (isAuthRoute(pathname)) return false; if (pathname.startsWith("/_next/")) return false; if (pathname === "/favicon.ico" || pathname === "/robots.txt" || pathname === "/sitemap.xml") return false; if (STATIC_FILE_PATTERN.test(pathname)) return false; return pathname === "/" || pathname.startsWith("/api/") || pathname.startsWith("/"); } export function getOidcProviderName(env: AuthEnv = process.env): string { return trimEnv(env.OIDC_PROVIDER_NAME) || "OIDC"; } export function getRequiredAuthSecret(env: AuthEnv = process.env): string { const secret = trimEnv(env.AUTH_SECRET); if (!secret) throw new Error("Missing required auth environment variable: AUTH_SECRET"); return secret; } export function mapOidcProfile(profile: OidcProfile) { const subject = String(profile.sub); const name = firstString(profile.name, profile.preferred_username, profile.email, subject); return { id: subject, name, email: typeof profile.email === "string" ? profile.email : null, image: typeof profile.picture === "string" ? profile.picture : null, }; } function trimEnv(value: string | undefined): string { return value?.trim() ?? ""; } function firstString(...values: unknown[]): string { for (const value of values) { if (typeof value === "string" && value.trim()) return value; } return ""; }