import NextAuth from "next-auth" import { authConfig } from "@/auth.config" /** * Middleware for session validation, route protection, and security headers * * This middleware: * - Validates session tokens on protected routes * - Redirects unauthenticated users to login * - Handles session expiration * - Allows access to auth pages for unauthenticated users * - Adds security headers (CSRF protection, XSS protection, etc.) * * Requirements: 3.3, 3.5, 9.4 (CSRF protection), 9.5 (security headers) */ const { auth } = NextAuth(authConfig) export default auth((req) => { // The authorization logic is handled in auth.config.ts authorized callback // Here we just add security headers const requestHeaders = new Headers(req.headers) // Add security headers - Requirement 9.4, 9.5 // CSRF Protection - SameSite cookie attribute is set in auth.ts // This header provides additional CSRF protection requestHeaders.set('X-Content-Type-Options', 'nosniff') // XSS Protection requestHeaders.set('X-XSS-Protection', '1; mode=block') // Prevent clickjacking attacks requestHeaders.set('X-Frame-Options', 'DENY') // Referrer Policy - don't leak referrer information requestHeaders.set('Referrer-Policy', 'strict-origin-when-cross-origin') // Content Security Policy - helps prevent XSS attacks // Note: This is a basic CSP. You may need to adjust based on your needs const csp = [ "default-src 'self'", "script-src 'self' 'unsafe-inline' 'unsafe-eval'", // unsafe-inline and unsafe-eval needed for Next.js "style-src 'self' 'unsafe-inline'", // unsafe-inline needed for Tailwind "img-src 'self' data: blob:", "font-src 'self' data:", "connect-src 'self'", "frame-ancestors 'none'", ].join('; ') requestHeaders.set('Content-Security-Policy', csp) // Permissions Policy - restrict access to browser features requestHeaders.set('Permissions-Policy', 'camera=(), microphone=(), geolocation=()') return undefined // Let NextAuth handle the response }) /** * Matcher configuration for middleware * Applies middleware to all routes except: * - API routes (handled separately) * - Static files (_next/static) * - Image optimization (_next/image) * - Favicon and other public assets */ export const config = { matcher: [ /* * Match all request paths except for the ones starting with: * - api (API routes) * - _next/static (static files) * - _next/image (image optimization files) * - favicon.ico (favicon file) * - public assets (images, icons, manifest, sw.js) */ "/((?!api|_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|json|js)$).*)", ], }