import { NextResponse } from 'next/server'; import type { NextRequest } from 'next/server'; // --------------------------------------------------------------------------- // Middleware — cheap cookie-presence route pre-filter // --------------------------------------------------------------------------- // Identity is owned by Ory Kratos. The authoritative session check is the // `whoami` call done client-side by (and server-side by the Go API // for every API request). Middleware only does a cheap pre-filter on the // presence of the `ory_kratos_session` cookie so that obviously-logged-out // users are bounced to /login without a flash of the app shell. // // The cookie's mere presence does NOT guarantee a valid session (it may be // expired) — that's why still re-verifies via `whoami`. // --------------------------------------------------------------------------- const SESSION_COOKIE = 'ory_kratos_session'; export function middleware(request: NextRequest) { const hasSession = Boolean(request.cookies.get(SESSION_COOKIE)?.value); const { pathname } = request.nextUrl; // Public paths that don't require auth. const publicPaths = [ '/', '/login', '/register', '/forgot-password', '/reset-password', '/verify-email', '/demo', '/help', ]; const isPublicPath = publicPaths.some( (p) => pathname === p || pathname.startsWith(p + '/'), ); const isApiPath = pathname.startsWith('/api/'); const isStaticPath = pathname.startsWith('/_next/') || pathname.startsWith('/favicon') || pathname.match(/\.(png|jpg|jpeg|gif|svg|ico|webp|woff2?|ttf|css|js)$/); // Skip middleware for API routes and static files. if (isApiPath || isStaticPath) return NextResponse.next(); // No session cookie + protected path -> redirect to login. if (!hasSession && !isPublicPath) { return NextResponse.redirect(new URL('/login', request.url)); } // Has a session cookie + on the login/register pages -> send to the app. // (AuthGate / whoami will catch the case where the cookie is stale.) if (hasSession && (pathname === '/login' || pathname === '/register')) { return NextResponse.redirect(new URL('/app', request.url)); } return NextResponse.next(); } export const config = { matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'], };