Auth.js v5 a schimbat API-ul față de NextAuth v4. Dacă migrezi un proiect, middleware-ul e locul unde se rupe totul.
Setup minim
În src/lib/auth.ts:
export const { auth, handlers, signIn, signOut } = NextAuth({
providers: [...],
session: { strategy: "jwt" },
});
Middleware: exportă direct auth
Nu mai ai withAuth ca în v4. Pur și simplu:
// src/middleware.ts
export { auth as middleware } from "@/lib/auth";
export const config = {
matcher: ["/dashboard/:path*", "/admin/:path*", "/api/private/:path*"],
};
Problema #1 — edge runtime
Auth.js v5 are un "auth.edge.ts" separat recomandat pentru middleware. Nu include provideri care au dependențe Node-only.
auth.ts— toate providerii, folosit în API routes și Server Componentsauth.edge.ts— doar provideri "edge-safe", folosit în middleware
Problema #2 — redirect loop
Dacă middleware-ul redirectează la /login când nu e autentificat, ai grijă ca /login să NU fie în matcher. Altfel loop infinit.
Bun:
matcher: ["/((?!login|register|api/auth|_next|.*\\..*).*)"]
Problema #3 — callbackUrl
După login vrei să te întorci la pagina protejată. În middleware:
if (!session?.user) {
const url = req.nextUrl.clone();
url.pathname = "/login";
url.searchParams.set("callbackUrl", req.nextUrl.pathname);
return NextResponse.redirect(url);
}
Pattern pentru rol-based
Middleware NU are acces la DB (edge). Verifici rolul din JWT:
callbacks: {
jwt({ token, user }) {
if (user) token.role = user.role;
return token;
},
session({ session, token }) {
if (session.user) session.user.role = token.role;
return session;
}
}
În middleware: if (token.role !== "ADMIN") redirect.
Test final
- Logged out →
/dashboard→ redirect la/login?callbackUrl=/dashboard - Logged in ca USER →
/admin→ 403 sau redirect - Logged in ca ADMIN →
/admin→ ajunge - Login din callbackUrl → întoarcere la
/dashboard
Dacă toate patru merg, ai protecție solidă.