Script Valley
Next.js: Full-Stack React Applications
Authentication with NextAuth.jsLesson 5.5

How to protect routes with NextAuth.js middleware

middleware with auth, authorized callback, protected route patterns, role-based access, redirecting unauthenticated users, matcher config

Auth Middleware

Protect routes at the edge before they render. Use the auth export from auth.ts as your middleware:

// middleware.ts
export { auth as middleware } from '@/auth'

export const config = {
  matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
}

The authorized callback in your authConfig controls the logic:

// auth.config.ts
callbacks: {
  authorized({ auth, request: { nextUrl } }) {
    const isLoggedIn = !!auth?.user
    const isProtected = nextUrl.pathname.startsWith('/dashboard')
      || nextUrl.pathname.startsWith('/settings')

    if (isProtected && !isLoggedIn) return false  // Redirect to signIn page
    return true
  },
},

Role-Based Access

authorized({ auth, request: { nextUrl } }) {
  const user = auth?.user as { role?: string } | undefined
  const isAdmin = user?.role === 'ADMIN'
  const isAdminRoute = nextUrl.pathname.startsWith('/admin')

  if (isAdminRoute && !isAdmin) {
    return Response.redirect(new URL('/unauthorized', nextUrl))
  }
  return true
}

Returning false from authorized redirects to the configured signIn page. Returning a Response.redirect() lets you redirect to a custom page like /unauthorized. The middleware runs on every request matched by the config, so keep the logic lightweight โ€” no database calls.

How to protect routes with NextAuth.js middleware โ€” Authentication with NextAuth.js โ€” Next.js: Full-Stack React Applications โ€” Script Valley โ€” Script Valley