saas_app/src/middleware.ts

63 lines
2 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).*)",
],
};