import { NextResponse } from "next/server"; import type { NextRequest } from "next/server"; import { getConfig } from "@/lib/config/load"; import { verifySessionCookieValue } from "@/lib/auth/session"; const PUBLIC_PATHS = [ "/login", "/api/auth/login", "/api/auth/session", "/api/healthz", ]; /** Optimistic (cookie-only) check - centralizes redirect logic per the Next.js Proxy guidance. * Every Route Handler also calls `requireAuth()` itself as the real, defense-in-depth check. */ export async function proxy(request: NextRequest) { const { config } = getConfig(); if (!config.auth.enabled) return NextResponse.next(); const { pathname } = request.nextUrl; if ( PUBLIC_PATHS.some( (path) => pathname === path || pathname.startsWith("/_next"), ) ) { return NextResponse.next(); } const isApiRoute = pathname.startsWith("/api/"); if (isApiRoute) { // Token-authed API clients won't have a session cookie; let the route handler's requireAuth() // do the real check instead of rejecting here. if (request.headers.get("authorization")?.startsWith("Bearer ")) return NextResponse.next(); } const sealed = request.cookies.get("triggershell_session")?.value; const session = await verifySessionCookieValue(sealed); if (!session?.userId) { if (isApiRoute) { return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); } const loginUrl = new URL("/login", request.url); loginUrl.searchParams.set("next", pathname); return NextResponse.redirect(loginUrl); } return NextResponse.next(); } export const config = { matcher: ["/((?!_next/static|_next/image|favicon.ico).*)"], };