Files
NetForge/src/middleware.ts
kevin-asprec 539564dbd4 feat(05-02): portal authentication via subscriber account number
- Add passwordHash field to Subscriber model (nullable for existing subscribers)
- Add portal-credentials NextAuth provider (accountNumber + password + tenantId)
- Persist subscriberId in JWT token and session for portal user identification
- Extend next-auth types with optional subscriberId on Session, User, and JWT
- Exclude /portal/login and /api/portal/auth from middleware auth requirement

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 17:22:52 +08:00

51 lines
1.6 KiB
TypeScript

import { withAuth } from "next-auth/middleware";
import { NextResponse } from "next/server";
export default withAuth(
function middleware(req) {
const { pathname } = req.nextUrl;
const token = req.nextauth.token;
// Super-admin route protection — check isSuperAdmin at middleware level
// This is an early gate; the layout and API handlers also enforce this.
if (pathname.startsWith("/admin")) {
if (!token?.isSuperAdmin) {
// Redirect non-super-admin users to login (or show forbidden)
const loginUrl = new URL("/login", req.url);
loginUrl.searchParams.set("callbackUrl", req.url);
return NextResponse.redirect(loginUrl);
}
}
// If user is authenticated (and passed super-admin check above), allow through
return NextResponse.next();
},
{
callbacks: {
authorized({ token }) {
// Return true if token exists (user is authenticated)
return !!token;
},
},
pages: {
signIn: "/login",
},
}
);
// Apply middleware to all routes EXCEPT public ones
export const config = {
matcher: [
/*
* Match all request paths EXCEPT:
* - /login (sign-in page)
* - /signup (registration page)
* - /api/auth/* (NextAuth endpoints)
* - /_next/* (Next.js internals)
* - /favicon.ico, /robots.txt, /sitemap.xml (static files)
* - Image files (.png, .jpg, .jpeg, .gif, .webp, .svg, .ico)
*/
"/((?!login|signup|portal/login|api/auth|api/portal/auth|_next/static|_next/image|favicon\\.ico|robots\\.txt|sitemap\\.xml|.*\\.(?:png|jpg|jpeg|gif|webp|svg|ico)).*)",
],
};