import { NextResponse } from "next/server"; import { buildContentSecurityPolicy, createCspNonce } from "@/lib/csp"; import { shouldRedirectAdminRequest } from "@/lib/proxy-access"; import { proxyAuth } from "@/lib/proxy-auth"; const SECURITY_HEADERS: Record = { "X-Content-Type-Options": "nosniff", "X-Frame-Options": "DENY", "X-XSS-Protection": "0", "Referrer-Policy": "strict-origin-when-cross-origin", "Permissions-Policy": "camera=(), microphone=(), geolocation=()", "Strict-Transport-Security": "max-age=63072000; includeSubDomains; preload", }; export const proxy = proxyAuth((req) => { if ( shouldRedirectAdminRequest(req.nextUrl.pathname, req.auth?.user ?? null) ) { return NextResponse.redirect(new URL("/login", req.url)); } const nonce = createCspNonce(); const csp = buildContentSecurityPolicy(nonce); const headers = new Headers(req.headers); headers.set("x-pathname", req.nextUrl.pathname); headers.set("x-nonce", nonce); const ip = req.headers.get("cf-connecting-ip") ?? req.headers.get("x-forwarded-for")?.split(",")[0]?.trim() ?? req.headers.get("x-real-ip") ?? ""; if (ip) headers.set("x-real-client-ip", ip); const response = NextResponse.next({ request: { headers } }); for (const [key, value] of Object.entries(SECURITY_HEADERS)) { response.headers.set(key, value); } response.headers.set("Content-Security-Policy", csp); return response; }); export const config = { matcher: ["/((?!api|_next/static|_next/image|assets|favicon.ico).*)"], };