-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathproxy.ts
More file actions
86 lines (75 loc) · 2.8 KB
/
Copy pathproxy.ts
File metadata and controls
86 lines (75 loc) · 2.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import { jwtVerify } from "jose";
import { prisma } from "@/lib/prisma";
const PROTECTED_PREFIXES = ["/dashboard", "/admin"];
const AUTH_PAGES = ["/login", "/registro", "/recuperar"];
const COOKIE_NAME = "plc_session";
function getSecret() {
const raw = process.env.AUTH_SECRET?.trim();
if (!raw) return null;
return new TextEncoder().encode(raw);
}
async function verifySessionJwt(token: string): Promise<{ sub: string; sid: string } | null> {
const secret = getSecret();
if (!secret) return null;
try {
const { payload } = await jwtVerify(token, secret);
if (!payload.sub || typeof payload.sid !== "string") return null;
return { sub: payload.sub as string, sid: payload.sid };
} catch {
return null;
}
}
// Node.js runtime — can hit the DB to verify session still exists
async function isActiveSession(token: string): Promise<boolean> {
const payload = await verifySessionJwt(token);
if (!payload) return false;
try {
const session = await prisma.session.findUnique({
where: { id: payload.sid },
select: { expires_at: true, user: { select: { is_active: true } } },
});
if (!session || session.expires_at < new Date()) return false;
if (!session.user?.is_active) return false;
return true;
} catch {
// DB unavailable — fall back to JWT-only validation
return true;
}
}
export async function middleware(request: NextRequest) {
const { pathname } = request.nextUrl;
const sessionCookie = request.cookies.get(COOKIE_NAME)?.value;
const isProtected = PROTECTED_PREFIXES.some((prefix) => pathname.startsWith(prefix));
const isAuthPage = AUTH_PAGES.some((page) => pathname.startsWith(page));
if (isProtected) {
if (!sessionCookie) {
const loginUrl = new URL("/login", request.url);
loginUrl.searchParams.set("next", pathname);
return NextResponse.redirect(loginUrl);
}
const valid = await isActiveSession(sessionCookie);
if (!valid) {
const loginUrl = new URL("/login", request.url);
loginUrl.searchParams.set("next", pathname);
const res = NextResponse.redirect(loginUrl);
res.cookies.set(COOKIE_NAME, "", { path: "/", maxAge: 0 });
return res;
}
}
if (isAuthPage && sessionCookie) {
const payload = await verifySessionJwt(sessionCookie);
if (payload) {
return NextResponse.redirect(new URL("/dashboard", request.url));
}
// Invalid/expired cookie — clear it and let them stay on the auth page
const response = NextResponse.next();
response.cookies.set(COOKIE_NAME, "", { path: "/", maxAge: 0 });
return response;
}
return NextResponse.next();
}
export const config = {
matcher: ["/dashboard/:path*", "/admin/:path*", "/login", "/registro", "/recuperar"],
};