Authentication

Implement production-grade authentication in Next.js — NextAuth v5, JWT strategies, session management, protected routes, and the multi-layer auth architecture used in enterprise apps.

Last reviewed: January 2025

·Next.js 13Next.js 14Next.js 15
✅
Quick Understanding: Authentication in Next.js App Router has three layers: middleware (fast edge redirect), layout (session validation + user data), and Server Components (permission checks). Use NextAuth v5 (Auth.js) or Clerk for the heavy lifting. Never roll your own auth from scratch.

🔍 What Is It?

Authentication in Next.js involves three layers working together:

  1. Middleware — runs at the edge, verifies JWT/session cookie, redirects unauthenticated users before the page loads
  2. Layout — fetches the full session, validates it, redirects if invalid, makes user data available to child pages
  3. Server Components / Route Handlers — check permissions for specific resources

Auth libraries for Next.js:

  • →NextAuth v5 (Auth.js) — open source, supports OAuth, email, credentials, database sessions
  • →Clerk — managed auth service, best DX, handles UI, MFA, organisations
  • →Lucia — lightweight, full control, good for custom auth requirements

🎯 Why Do We Need It?

Auth is one of the most complex parts of any web app. Getting it wrong has serious consequences:

  • →Unauthorised data access
  • →Session fixation attacks
  • →CSRF vulnerabilities
  • →Token leakage

Using a battle-tested library (NextAuth, Clerk) handles these edge cases. The App Router's multi-layer approach gives you both performance (edge redirects) and correctness (server-side session validation).

🏗️ What Happens in Real Projects?

Auth architecture in a SaaS product:

  • →Public routes: /, /pricing, /blog — no auth required
  • →Auth routes: /login, /register — redirect authenticated users to dashboard
  • →Protected routes: /dashboard, /settings — redirect unauthenticated users to login
  • →Admin routes: /admin — require role = 'admin'
  • →API routes: /api/v1/* — require Bearer token

⚙️ How It Works

Auth.js (NextAuth v5) flow:

  1. User submits credentials or clicks OAuth provider
  2. Auth.js validates credentials / exchanges OAuth code
  3. Creates a session (JWT or database session)
  4. Sets a session cookie (httpOnly, secure, sameSite)
  5. Middleware reads the cookie, verifies JWT on every request
  6. Session data available in Server Components via auth()

💻 Example

NextAuth v5 Setup and Multi-layer Auth — Complete auth setup with middleware, layout protection, and Server Component session access.

ts
// auth.ts (project root)
import NextAuth from 'next-auth';
import GitHub from 'next-auth/providers/github';
import Credentials from 'next-auth/providers/credentials';
import { db } from '@/lib/db';
import { verifyPassword } from '@/lib/crypto';

export const { handlers, signIn, signOut, auth } = NextAuth({
  providers: [
    GitHub,
    Credentials({
      credentials: {
        email: { label: 'Email', type: 'email' },
        password: { label: 'Password', type: 'password' },
      },
      authorize: async ({ email, password }) => {
        const user = await db.user.findUnique({ where: { email: email as string } });
        if (!user || !user.passwordHash) return null;
        const valid = await verifyPassword(password as string, user.passwordHash);
        if (!valid) return null;
        return { id: user.id, email: user.email, name: user.name, role: user.role };
      },
    }),
  ],
  callbacks: {
    jwt({ token, user }) {
      if (user) token.role = (user as any).role;
      return token;
    },
    session({ session, token }) {
      session.user.role = token.role as string;
      return session;
    },
  },
});

🤔 Common Confusions

❓ Should I use JWT sessions or database sessions?

JWT sessions are stateless — no DB lookup per request, works on edge. Database sessions allow instant revocation — delete the session row and the user is logged out immediately. Use JWT for most apps. Use database sessions when you need instant revocation (security-critical apps, enterprise SSO).

❓ Is middleware auth check enough, or do I need layout checks too?

Both. Middleware is the fast first line of defence — it redirects unauthenticated users before any page code runs. But middleware uses a lightweight JWT check. Layouts do the full session validation (DB lookup if needed) and make the user object available. Never skip the layout check.

❓ How do I implement role-based access control (RBAC)?

Add role to the JWT token in the jwt callback. Check session.user.role in Server Components. For complex RBAC, use a permissions library like Casbin or implement a simple permissions check function: can(user, "edit", "product"). Never check roles in Client Components — it is bypassable.

🚨 Common Production Issues

Session not updating after role change — JWT sessions are cached in the token. If you update a user's role in the DB, the JWT still has the old role until it expires. Force a re-login or use database sessions for role-sensitive apps.

CSRF on Route Handlers — POST endpoints that use cookie-based auth are vulnerable to CSRF. NextAuth handles this for its own endpoints. For custom Route Handlers, verify the Origin header or use CSRF tokens.

Exposing session data to Client Components — never pass the full session object to Client Components. Only pass the minimum needed (user name, avatar URL). Sensitive data (role, permissions, tokens) should only be used in Server Components.

✅ Best Practices

Use NextAuth v5 or Clerk — never roll your own auth

Three-layer auth: middleware (edge redirect) + layout (session validation) + component (permission check)

Add role to JWT token — available in middleware without a DB lookup

Use httpOnly, secure, sameSite=strict cookies — never store tokens in localStorage

Implement logout that clears both the cookie and invalidates the server-side session

🏛️ Architect's Note

Senior Architect's Perspective

Authentication is the most security-critical part of your application. The three-layer model (middleware + layout + component) provides defence in depth. Even if one layer has a bug, the others catch it. Invest in getting auth right from day one — retrofitting auth into an existing app is significantly harder than building it in from the start.

💬 Frequently Asked Questions

What is the difference between NextAuth v4 and v5?

NextAuth v5 (Auth.js) is a complete rewrite for the App Router. Key changes: the auth() function works in Server Components and middleware, the Route Handler is at app/api/auth/[...nextauth]/route.ts, and the configuration is in auth.ts at the root. v4 is for Pages Router; v5 is for App Router.

Should I use Clerk or NextAuth?

Clerk for the best developer experience and when you want managed auth (no infrastructure to maintain). NextAuth for open-source, self-hosted, or when you need deep customisation. Clerk is significantly faster to implement but has a monthly cost per user.

How do I implement magic link (passwordless) auth?

NextAuth has a built-in Email provider that sends magic links. Configure it with a Resend or SendGrid adapter. The flow: user enters email → magic link sent → user clicks link → session created. No password required.

🎯 Key Takeaways

1Three-layer auth: middleware (fast redirect) + layout (session validation) + component (permissions)
2Use NextAuth v5 or Clerk — never implement auth from scratch
3JWT sessions for performance, database sessions for instant revocation
4Add role to JWT — available in middleware without a DB lookup
5Never store auth tokens in localStorage — use httpOnly cookies
6Check permissions in Server Components, never in Client Components

🎯 Practice this topic in interviews

↗ Where this topic fits

Sources

Sources / References

Use these Next.js references to verify the concept in official docs and continue into the most relevant SplashRide pages.

Related SplashRide pages

SplashRide Next.js learning path

Browse the full Next.js topic collection and learning order on SplashRide.

Next.js Interview Prep

Practice Next.js interview questions and scenario-based answers.

Frontend Engineer Career Path

A beginner-friendly journey through web foundations, React, production frontend engineering, and interview preparation.

Full Stack Java Developer Career Path

A guided route through frontend foundations, Java backend engineering, delivery workflows, and interview readiness.

Middleware

Master Next.js Middleware — the edge function that runs before every request, enabling auth redirects, A/B testing, geolocation, and request modification at the CDN edge.

Route Handlers

Master Route Handlers in Next.js — the App Router replacement for API routes, supporting all HTTP methods, streaming responses, and edge runtime.