Skip to main content
Authentication in Next.js involves three concepts:
  1. Authentication — Verifies the user’s identity (username/password, OAuth, etc.)
  2. Session management — Tracks auth state across requests using cookies or a database
  3. Authorization — Determines what routes and data the authenticated user can access
For increased security and simplicity, use an auth library rather than building your own solution from scratch.

Sign-up and login

Use the HTML <form> element with Server Actions and useActionState to capture credentials, validate fields, and call your auth provider.
1

Capture user credentials

Create a form that invokes a Server Action on submission:
2

Validate form fields on the server

Use Zod or a similar schema library to validate form fields server-side:
3

Create a user or check credentials

After validation, insert the user or check credentials against your database:

Session management

There are two types of sessions:
  • Stateless — Session data (JWT) stored in the browser’s cookies. Simpler but must be implemented carefully.
  • Database — Session data stored server-side; only an encrypted session ID is stored in the cookie.
Use a session management library like iron-session or Jose rather than managing encryption yourself.

Stateless sessions

1

Generate a secret key

Store it as an environment variable:
2

Encrypt and decrypt sessions

3

Set session cookies

Recommended cookie options:
  • httpOnly — Prevents client-side JavaScript from accessing the cookie
  • secure — Only send over HTTPS
  • sameSite — Controls cross-site request behavior
  • expires / maxAge — Automatic cookie expiry
4

Update and delete sessions

Use deleteSession() on logout:

Authorization

Middleware (optimistic checks)

Use middleware for fast, optimistic route protection based on session cookies. Because middleware runs on every route, only perform cookie-based checks here — avoid database queries to prevent performance issues.
Middleware should not be your only line of defense. Perform auth checks as close to your data source as possible.

Data Access Layer (DAL)

Centralize your authorization logic in a DAL with a verifySession() function:
Call verifySession() in Server Components, Server Actions, and Route Handlers:

Data Transfer Objects (DTO)

Only return the minimum data needed. Use DTOs to filter fields based on viewer permissions:

Auth libraries

Rather than building your own solution, consider these authentication libraries:

NextAuth.js

Full-featured authentication with OAuth, email/password, and JWT support.

Clerk

Hosted auth with pre-built UI components and extensive customization.

Auth0

Enterprise-grade auth platform with social logins and MFA.

Kinde

Simple auth for modern web apps with built-in multi-tenancy.