import { NextResponse } from 'next/server'; import type { NextRequest } from 'next/server'; import { getToken } from 'next-auth/jwt'; // Define paths that don't require authentication const publicPaths = [ '/api/auth', '/signin', '/loggedout', '/register', '/error', '/images', '/fonts', '/favicon.ico', '/robots.txt', '/sitemap.xml', ]; // Check if the requested path is public function isPublicPath(path: string): boolean { return publicPaths.some(publicPath => path.startsWith(publicPath)); } export async function middleware(request: NextRequest) { const { pathname } = request.nextUrl; // Check if the path is public (no authentication needed) if (isPublicPath(pathname)) { return NextResponse.next(); } // For API routes, check for token in the request if (pathname.startsWith('/api/')) { try { // Verify authentication token const token = await getToken({ req: request, secret: process.env.NEXTAUTH_SECRET }); if (!token) { // No token found, redirect to sign-in page or return 401 for API requests return NextResponse.json( { error: 'Authentication required' }, { status: 401 } ); } // Check if token is expired if (token.accessTokenExpires && (token.accessTokenExpires as number) < Date.now()) { return NextResponse.json( { error: 'Session expired' }, { status: 401 } ); } // Token is valid, proceed return NextResponse.next(); } catch (error) { console.error('Auth middleware error:', error); return NextResponse.json( { error: 'Authentication error' }, { status: 401 } ); } } // For page routes, verify session try { const token = await getToken({ req: request, secret: process.env.NEXTAUTH_SECRET }); // If no token found, redirect to sign-in page if (!token) { const url = new URL('/signin', request.url); url.searchParams.set('callbackUrl', encodeURI(request.url)); return NextResponse.redirect(url); } // Check if token is expired if (token.accessTokenExpires && (token.accessTokenExpires as number) < Date.now()) { const url = new URL('/signin', request.url); url.searchParams.set('callbackUrl', encodeURI(request.url)); url.searchParams.set('error', 'SessionExpired'); return NextResponse.redirect(url); } // If authorized, proceed to the requested page return NextResponse.next(); } catch (error) { console.error('Auth middleware error:', error); const url = new URL('/signin', request.url); url.searchParams.set('error', 'AuthError'); return NextResponse.redirect(url); } } // Only run middleware on matching paths export const config = { matcher: [ /* * Match all request paths except: * 1. /_next (Next.js internals) * 2. /static (static files) * 3. /images (public images) * 4. /fonts (public fonts) * 5. /favicon.ico, /robots.txt, /sitemap.xml (SEO files) */ '/((?!_next/|static/|images/|fonts/|favicon.ico|robots.txt|sitemap.xml).*)', ], };