Neah/middleware.ts
2025-05-02 11:41:43 +02:00

113 lines
3.1 KiB
TypeScript

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).*)',
],
};