Back to Next.js tutorials
Advanced15 min read

Authentication Patterns

Secure sessions, middleware guards, and auth integration patterns in Next.js App Router.

Session Strategies

Cookie-based sessions (HttpOnly, Secure, SameSite) are standard for web apps — tokens inaccessible to JavaScript reduce XSS impact. JWT in memory or short-lived access tokens pair with refresh token rotation for SPAs.

Libraries like Auth.js (NextAuth), Clerk, and Lucia provide Next.js integrations. Choose based on OAuth provider needs, self-hosting requirements, and database session storage preferences.

  • HttpOnly cookies for session tokens
  • Auth.js, Clerk, Lucia integrations
  • Match strategy to OAuth and hosting needs

Middleware Protection

middleware.ts runs before routes match — verify session cookie, redirect unauthenticated users to login, attach headers. Matcher config limits middleware to protected path patterns for performance.

Middleware cannot access database directly in Edge runtime without compatible drivers — verify JWT signature or call auth service API. Keep middleware fast — it runs on every matched request.

  • middleware.ts before route render
  • Matcher limits scope
  • Edge-compatible auth checks only
export function middleware(request) {
  if (!request.cookies.get('session')) {
    return NextResponse.redirect(new URL('/login', request.url));
  }
}
export const config = { matcher: ['/dashboard/:path*'] };

Server Component Auth Checks

Defense in depth — verify session in Server Components and Server Actions even after middleware passes. Middleware can be bypassed in edge cases; server data access must always authorize.

Fetch current user once in layout, pass to children via context (client) or props (server). Avoid N+1 auth lookups per nested server component.

  • Authorize in Server Actions always
  • Defense in depth beyond middleware
  • Fetch user once in layout

OAuth and Callback Routes

OAuth flows use Route Handlers or Auth.js catch-all routes for callbacks. State parameter prevents CSRF on OAuth initiation. Store PKCE verifiers for public clients.

Redirect URLs must match provider console configuration exactly — include localhost variants for development. Handle OAuth errors gracefully with user-friendly messages.

  • Dedicated callback route handlers
  • CSRF state and PKCE
  • Exact redirect URL configuration

Role-Based Access

Model roles and permissions in session or fetch from database on each request for sensitive apps. notFound() instead of 403 when hiding resource existence. Explicit 403 pages when denial reason should be visible.

Server Actions verify ownership before mutations — `{ postId }` from FormData must belong to authenticated user. Never trust client-sent user IDs as authorization proof.

  • Verify roles server-side
  • notFound vs 403 semantics
  • Ownership checks in every mutation

Get In Touch


Ready to discuss your next project? Drop me a message.