saas_app/src/middleware.ts

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