import NextAuth from "next-auth"; import { NextResponse } from "next/server"; import authConfig from "@/auth.config"; // Route-gating for page requests: "everything requires login by default, // explicit allowlist for what doesn't" (safer than an opt-in allowlist that // new routes can forget to add themselves to). // // This project pins Next.js 14.2.35, which predates Next.js 16's // middleware.ts -> proxy.ts rename (see https://nextjs.org/docs/messages/middleware-to-proxy) // so this stays middleware.ts with a default-exported `middleware` function, // not proxy.ts. Auth.js v5's docs (https://authjs.dev/getting-started/session-management/protecting) // confirm: older Next.js versions re-export `auth` as `middleware`; only // Next.js 16+ uses `proxy`. // // Deliberately builds its own NextAuth instance from src/auth.config.ts // (no Credentials provider) instead of importing `auth` from src/auth.ts — // this file runs on the Edge Runtime, and src/auth.ts's Credentials // provider pulls in bcryptjs (Node-only); see auth.config.ts's comment. // This instance only needs to decode/validate the JWT session cookie, which // is Edge-safe. // // config.matcher below excludes /api entirely, so this middleware never // runs on API routes (including /api/auth/* itself, needed for the login // flow) — API route authorization is handled separately, directly in each // route handler (see src/app/api/requests/route.ts), per Auth.js's own // guidance to verify the session as close to the data fetching as possible // rather than relying on middleware alone. That also means /login doesn't // need special-casing in the matcher, only in the redirect check below (to // avoid an infinite redirect loop), and Next.js's internal asset paths // (_next/static, _next/image, favicon.ico) never reach this middleware. const { auth } = NextAuth(authConfig); export default auth((req) => { const isLoginPage = req.nextUrl.pathname === "/login"; if (!req.auth && !isLoginPage) { const loginUrl = new URL("/login", req.nextUrl.origin); return NextResponse.redirect(loginUrl); } return NextResponse.next(); }); export const config = { matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"], };