payment-backoffice/middleware.ts
2025-10-25 11:39:24 +02:00

82 lines
2.1 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import { jwtVerify } from "jose";
const COOKIE_NAME = "auth_token";
const JWT_SECRET = new TextEncoder().encode(process.env.JWT_SECRET!);
function isExpired(exp?: number) {
return exp ? exp * 1000 <= Date.now() : false;
}
async function validateToken(token: string) {
const raw = token.startsWith("Bearer ") ? token.slice(7) : token;
try {
const { payload } = await jwtVerify(raw, JWT_SECRET, {
algorithms: ["HS256"],
});
return payload as {
exp?: number;
MustChangePassword?: boolean;
[key: string]: unknown;
};
} catch (err) {
console.error("Token validation error:", err);
return null;
}
}
export async function middleware(request: NextRequest) {
const token = request.cookies.get(COOKIE_NAME)?.value;
const loginUrl = new URL("/login", request.url);
const currentPath = request.nextUrl.pathname;
// 1⃣ No token
if (!token) {
loginUrl.searchParams.set("reason", "no-token");
loginUrl.searchParams.set("redirect", currentPath);
return NextResponse.redirect(loginUrl);
}
// 2⃣ Validate + decode
const payload = await validateToken(token);
if (!payload) {
const res = NextResponse.redirect(loginUrl);
res.cookies.delete(COOKIE_NAME);
loginUrl.searchParams.set("reason", "invalid-token");
loginUrl.searchParams.set("redirect", currentPath);
return res;
}
// 3⃣ Expiry check
if (isExpired(payload.exp)) {
const res = NextResponse.redirect(loginUrl);
res.cookies.delete(COOKIE_NAME);
loginUrl.searchParams.set("reason", "expired-token");
loginUrl.searchParams.set("redirect", currentPath);
return res;
}
// 4⃣ Must change password check
if (payload.MustChangePassword) {
loginUrl.searchParams.set("reason", "change-password");
loginUrl.searchParams.set("redirect", currentPath);
return NextResponse.redirect(loginUrl);
}
// ✅ All good
return NextResponse.next();
}
export const config = {
matcher: [
"/dashboard/:path*",
"/settings/:path*",
"/admin/:path*",
"/change-password/:path*",
],
};