59 lines
1.8 KiB
TypeScript
59 lines
1.8 KiB
TypeScript
import jwt from 'jsonwebtoken';
|
|
import { NextResponse, type MiddlewareConfig, type NextRequest } from 'next/server';
|
|
|
|
const publicRoutes = [
|
|
{ path: '/login', whenAuthenticated: 'redirect' },
|
|
{ path: '/register', whenAuthenticated: 'redirect' },
|
|
{ path: '/', whenAuthenticated: 'next' },
|
|
] as const;
|
|
|
|
const ROOT_PATH = '/login'; // url raiz
|
|
|
|
export function middleware(request: NextRequest) {
|
|
const path = request.nextUrl.pathname;
|
|
const publicRoute = publicRoutes.find((route) => route.path === path);
|
|
const authToken = request.cookies.get('access_token');
|
|
|
|
// 1. Não autenticado e rota pública → segue normal
|
|
if (!authToken && publicRoute) {
|
|
return NextResponse.next();
|
|
}
|
|
|
|
// 2. Não autenticado e rota privada → redireciona para raiz
|
|
if (!authToken && !publicRoute) {
|
|
return NextResponse.redirect(new URL(ROOT_PATH, request.url));
|
|
}
|
|
|
|
// 3. Autenticado em rota pública com flag "redirect" → vai para raiz
|
|
if (authToken && publicRoute && publicRoute.whenAuthenticated === 'redirect') {
|
|
return NextResponse.redirect(new URL(ROOT_PATH, request.url));
|
|
}
|
|
|
|
// 4. Autenticado em rota privada → valida token
|
|
if (authToken && !publicRoute) {
|
|
const decoded: any = jwt.decode(authToken.value);
|
|
|
|
if (!decoded || !decoded.exp) {
|
|
console.log('Token inválido');
|
|
return NextResponse.redirect(new URL(ROOT_PATH, request.url));
|
|
}
|
|
|
|
const currentTime = Math.floor(Date.now() / 1000);
|
|
|
|
if (decoded.exp <= currentTime) {
|
|
console.log('Token expirado');
|
|
return NextResponse.redirect(new URL(ROOT_PATH, request.url));
|
|
}
|
|
|
|
return NextResponse.next();
|
|
}
|
|
|
|
return NextResponse.next();
|
|
}
|
|
|
|
export const config: MiddlewareConfig = {
|
|
matcher: [
|
|
// ignora APIs, arquivos estáticos e metadados
|
|
'/((?!api|_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt|images).*)',
|
|
],
|
|
};
|