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