Skip to content
·3 min read

Next.js Middleware for Auth — The Patterns That Actually Work

Next.js middleware is the worst-documented feature in the framework. Edge runtime limits, JWT verification gotchas, redirect loops. Here's the setup I ship.

Next.jsAuthenticationMiddlewareWeb Dev

Next.js middleware is the worst-documented feature in the framework. The official docs show you a hello-world example, ship it, and discover in production that JWT verification fails, your users hit redirect loops, and half your database library doesn't work.

I've shipped middleware-based auth on three production apps. Here's the setup I use, after all the bugs.

The mental model

Middleware runs on every request before the route handler. It runs on the Edge Runtime by default, which is a restricted sandbox — no Node built-ins like crypto or fs. It's fast (cold start in milliseconds) but limiting.

// middleware.ts (in the root of your project, next to app/)
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
 
export function middleware(request: NextRequest) {
  // Runs on every matched request
  return NextResponse.next()
}
 
export const config = {
  matcher: ['/dashboard/:path*', '/admin/:path*'],
}