-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathauth.config.ts
More file actions
83 lines (75 loc) · 2.95 KB
/
Copy pathauth.config.ts
File metadata and controls
83 lines (75 loc) · 2.95 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
import type { NextAuthConfig } from "next-auth";
import { NextResponse } from "next/server";
const authConfig = {
providers: [],
pages: {
signIn: "/auth/login",
},
callbacks: {
// CLAUDE FIX: Without this callback, authConfig (used by the edge middleware)
// has no session callback, so auth.user.role is always undefined in the
// authorized() check below. Any admin route the router-cache hasn't seen
// before gets a fresh server request → middleware fires → role is missing →
// redirect to /dashboard. Mapping token.role here is edge-safe (no DB call).
session({ session, token }) {
if (session.user) {
session.user.role = token.role as string as never;
}
return session;
},
authorized({ auth, request }) {
const pathname = request.nextUrl.pathname;
const isAuthed = Boolean(auth?.user);
const isAuthRoute = pathname.startsWith("/auth");
const isAdminRoute = pathname.startsWith("/admin");
const isPublicRoute =
pathname === "/" || pathname.startsWith("/signals/track-record");
// AUDIT FIX: Treat /api/auth/* as always allowed — NextAuth's own endpoints
// must never be blocked by this guard.
if (pathname.startsWith("/api/auth")) {
return true;
}
if (isPublicRoute) {
return true;
}
// AUDIT FIX: Previously returned `false` for authenticated users on auth routes,
// which caused NextAuth to redirect to /auth/login again — an infinite loop.
// Now explicitly redirect to /dashboard to break the cycle.
if (isAuthRoute) {
if (isAuthed) {
return NextResponse.redirect(new URL("/dashboard", request.url));
}
return true;
}
const isProtectedRoute =
pathname.startsWith("/dashboard") ||
pathname.startsWith("/journal") ||
pathname.startsWith("/signals") ||
pathname.startsWith("/outlook") ||
pathname.startsWith("/analytics") ||
pathname.startsWith("/education") ||
pathname.startsWith("/calculator") ||
pathname.startsWith("/community") ||
pathname.startsWith("/watchlist") ||
pathname.startsWith("/notifications") ||
pathname.startsWith("/profile");
if (isProtectedRoute) {
return isAuthed;
}
// AUDIT FIX: Admin routes now enforce the ADMIN role at the middleware level,
// not just at the individual API handler level. Non-admin authenticated users
// are redirected to /dashboard instead of seeing admin UI that will fail all
// its data fetches with 403s.
if (isAdminRoute) {
if (!isAuthed) return false;
const userRole = (auth?.user as { role?: string } | undefined)?.role;
if (userRole !== "ADMIN") {
return NextResponse.redirect(new URL("/dashboard", request.url));
}
return true;
}
return true;
},
},
} satisfies NextAuthConfig;
export default authConfig;