Files
ubi-dan-itam/src/middleware.ts
T
toanhoang 65029480a9 feat: add middleware for page route protection
middleware.ts gates page routes by default (redirect to /login when
unauthenticated), except /login itself and Next.js internal asset
paths - config.matcher excludes /api entirely, /_next/static,
/_next/image, and favicon.ico. Default-deny: everything requires login
unless explicitly excluded, including the home page, rather than an
opt-in allowlist new routes could forget to join.

Builds its own lightweight NextAuth instance from auth.config.ts
(no Credentials provider) instead of importing auth from auth.ts, to
stay Edge-Runtime compatible - see auth.config.ts.

API routes are deliberately NOT gated here (config.matcher excludes
/api). Auth.js guidance is to verify the session as close to the data
fetching as possible rather than rely on middleware alone; API route
auth is added directly in each route handler instead (next commit).

This project pins Next.js 14.2.35, which predates the Next.js 16
middleware.ts -> proxy.ts rename, so this stays middleware.ts with a
default export, not proxy.ts.
2026-07-31 12:38:12 +07:00

48 lines
2.2 KiB
TypeScript

import NextAuth from "next-auth";
import { NextResponse } from "next/server";
import authConfig from "@/auth.config";
// Route-gating for page requests: "everything requires login by default,
// explicit allowlist for what doesn't" (safer than an opt-in allowlist that
// new routes can forget to add themselves to).
//
// This project pins Next.js 14.2.35, which predates Next.js 16's
// middleware.ts -> proxy.ts rename (see https://nextjs.org/docs/messages/middleware-to-proxy)
// so this stays middleware.ts with a default-exported `middleware` function,
// not proxy.ts. Auth.js v5's docs (https://authjs.dev/getting-started/session-management/protecting)
// confirm: older Next.js versions re-export `auth` as `middleware`; only
// Next.js 16+ uses `proxy`.
//
// Deliberately builds its own NextAuth instance from src/auth.config.ts
// (no Credentials provider) instead of importing `auth` from src/auth.ts —
// this file runs on the Edge Runtime, and src/auth.ts's Credentials
// provider pulls in bcryptjs (Node-only); see auth.config.ts's comment.
// This instance only needs to decode/validate the JWT session cookie, which
// is Edge-safe.
//
// config.matcher below excludes /api entirely, so this middleware never
// runs on API routes (including /api/auth/* itself, needed for the login
// flow) — API route authorization is handled separately, directly in each
// route handler (see src/app/api/requests/route.ts), per Auth.js's own
// guidance to verify the session as close to the data fetching as possible
// rather than relying on middleware alone. That also means /login doesn't
// need special-casing in the matcher, only in the redirect check below (to
// avoid an infinite redirect loop), and Next.js's internal asset paths
// (_next/static, _next/image, favicon.ico) never reach this middleware.
const { auth } = NextAuth(authConfig);
export default auth((req) => {
const isLoginPage = req.nextUrl.pathname === "/login";
if (!req.auth && !isLoginPage) {
const loginUrl = new URL("/login", req.nextUrl.origin);
return NextResponse.redirect(loginUrl);
}
return NextResponse.next();
});
export const config = {
matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
};