import { NextResponse } from 'next/server'; import type { NextRequest } from 'next/server'; import { jwtVerify } from 'jose'; const SECRET_KEY = new TextEncoder().encode(process.env.JWT_SECRET || 'fallback-secret-key-change-me'); export async function middleware(request: NextRequest) { const session = request.cookies.get('session')?.value; const { pathname } = request.nextUrl; // Paths that are always public const publicPaths = [ '/login', '/register', '/api/auth/login', '/api/auth/register', '/api/auth/verify-otp', '/api/auth/send' ]; // Static assets and Next.js internals if ( pathname.startsWith('/_next') || pathname.startsWith('/static') || pathname.includes('.') // images, icons, etc ) { return NextResponse.next(); } const isPublic = publicPaths.some(path => pathname.startsWith(path)); // If user has session, try to verify it let isValidSession = false; if (session) { try { await jwtVerify(session, SECRET_KEY); isValidSession = true; } catch (e) { isValidSession = false; } } // Logic: // 1. If public path and Logged In -> Redirect to Dashboard if (isPublic && isValidSession && (pathname === '/login' || pathname === '/register')) { return NextResponse.redirect(new URL('/', request.url)); } // 2. If public path -> Allow if (isPublic) { return NextResponse.next(); } // 3. If protected path and Not Logged In -> Redirect to Login if (!isValidSession) { const loginUrl = new URL('/login', request.url); // Optional: Add ?from=pathname to redirect back after login return NextResponse.redirect(loginUrl); } // 4. Protected path and Logged In -> Allow return NextResponse.next(); } export const config = { matcher: [ /* * Match all request paths except for the ones starting with: * - api (API routes) -> Wait, we WANT to protect API routes except auth ones * - _next/static (static files) * - _next/image (image optimization files) * - favicon.ico (favicon file) */ '/((?!_next/static|_next/image|favicon.ico).*)', ], };