next-api-layerNext API Layer
DocumentationAPI ReferenceExamples
next-api-layerNext API Layer

Production-grade API layer for Next.js with external JWT backends.

Documentation

  • Introduction
  • Installation
  • Quick Start
  • API Reference

Resources

  • Examples
  • Proxy
  • API Client
  • AuthProvider

Community

  • GitHub
  • Issues
  • Discussions
  • Contact

© 2026 Next API Layer. All rights reserved.

Created by
Documentation

Getting Started

  • Introduction
  • Installation
  • Quick Start

Core Concepts

  • How It Works
  • Token Management
  • Guest Tokens

Configuration

  • Auth Proxy
  • Proxy Handler
  • API Client
  • Security
  • i18n Integration

Client Side

  • AuthProvider
  • useAuth Hook

API Reference

  • API Reference
  • Types

Examples

  • Examples
  • Authentication Patterns
  • Role-Based Access
  • API Routes
  • Forms
  • Data Fetching
Changelog

Getting Started

  • Introduction
  • Installation
  • Quick Start

Core Concepts

  • How It Works
  • Token Management
  • Guest Tokens

Configuration

  • Auth Proxy
  • Proxy Handler
  • API Client
  • Security
  • i18n Integration

Client Side

  • AuthProvider
  • useAuth Hook

API Reference

  • API Reference
  • Types

Examples

  • Examples
  • Authentication Patterns
  • Role-Based Access
  • API Routes
  • Forms
  • Data Fetching
Changelog

Token Management

next-api-layer handles JWT token management automatically, including validation, refresh, single-flight coalescing, and optional local verification.

Overview#

The library manages these token operations:

  1. Validation: Checking if a token is valid (backend per-request, or local JWT verification)
  2. Refresh: Automatically refreshing expired tokens, coalescing concurrent refreshes
  3. Reuse detection: Classifying refresh failures and failing closed on token theft (RFC 9700)

Token Validation#

Every request triggers token validation through your backend's validate endpoint:

TypeScript
Loading...

Expected Response Format#

Your backend's /auth/me endpoint should return:

JSON
Loading...

Custom Response Parsing#

If your backend uses a different format, use responseMappers:

TypeScript
Loading...

Automatic Token Refresh#

When a token is invalid or expired, the library automatically attempts to refresh it:

TypeScript
Loading...

Refresh Flow#

  1. Token validation fails (expired/invalid)
  2. Library calls /auth/refresh with current token
  3. If successful, updates cookie with new token
  4. Sets x-refreshed-token header for the request
  5. Continues with the original request

Expected Refresh Response#

JSON
Loading...

Custom Refresh Parsing#

TypeScript
Loading...

Concurrent Refresh (Single-Flight)#

When several requests arrive at once with the same expired token (navigation + SWR polling + RSC fetches), the proxy coalesces their refreshes into a single auth/refresh call and shares the result:

Loading...

This matters for backends that rotate jti server-side: without coalescing, the second refresh would replay a rotated token and bounce the user to login (or orphan the session). Enabled by default (refresh.singleFlight), effective within a single runtime instance.

Across separate serverless/edge isolates, concurrent requests may still trigger independent refreshes. Pair with idempotent refresh handling (a rotation grace window) on the backend for full coverage.

Proactive Refresh#

By default, refresh is reactive — triggered only after a 401. Enable proactive refresh to renew a still-valid token shortly before it expires, avoiding a guaranteed failed roundtrip on the next cycle:

TypeScript
Loading...

Proactive refresh is best-effort: if it fails, the still-valid token keeps working. A detected token reuse remains terminal.

Reuse Detection & Fail-Closed (RFC 9700)#

A failed refresh is classified so you can react to token theft:

reasonMeaningDefault trigger
expiredToken past its lifetime401
revokedServer rejected the token403
reuseA rotated (old) token was replayed409 or body { code: 'token_reuse' }
networkTransport errorfetch threw
unknownAnything else—
TypeScript
Loading...

On reuse — or when access.guestFallbackOnUserRefreshFail: false — the proxy clears every auth cookie and redirects to login (or 401 for API routes), emitting auth:reuse / auth:refresh:fail audit events. It never downgrades to a guest session.

Local Validation (Stateless)#

By default the proxy calls auth/me on every request. Switch to local verification to validate the JWT in-process and remove the per-request backend roundtrip:

TypeScript
Loading...

revalidateInterval preserves revocation / allowlist enforcement: the backend is consulted at most once every N seconds (tracked via the non-sensitive __nal_rv cookie). Use validate.verify for RS256 / JWKS.

Dual-Token Mode#

For the OAuth2 access/refresh split — a short-lived access token plus a separate, long-lived refresh token — name a refresh cookie:

TypeScript
Loading...

The access token is validated on each request; only the refresh cookie is sent to auth/refresh, which rotates both tokens. Even if the access token leaks in a log or proxy, it is short-lived.

Token Types#

The library supports different token types:

TypeScript
Loading...

Type Checking#

TypeScript
Loading...

Guest vs User Tokens#

FeatureGuest TokenUser Token
Created automaticallyYesNo (login required)
Cookie nameguestTokenuserToken
Typical TTL1 hour7 days
Can access protected routesNoYes

Cookie Configuration#

Control how tokens are stored:

TypeScript
Loading...

Security Best Practices#

  • Always use httpOnly: true to prevent XSS token theft
  • Use secure: true in production for HTTPS-only
  • sameSite: 'lax' provides good CSRF protection while allowing normal navigation
  • Set appropriate maxAge based on your security requirements

Accessing Tokens#

In Route Handlers#

TypeScript
Loading...

With API Client#

The API client handles token retrieval automatically:

TypeScript
Loading...

Token Expiration Handling#

Proxy Level#

The proxy handles expiration automatically:

  1. Detects expired token from validation response
  2. Attempts refresh
  3. If refresh fails, clears cookies and redirects to login (for protected routes)

Client Level#

The AuthProvider keeps client state in sync:

TypeScript
Loading...

Debugging#

Enable audit logging to track token operations:

TypeScript
Loading...

This helps identify:

  • Frequent refresh attempts (might indicate short token TTL)
  • Failed validations (might indicate backend issues)
  • Unauthorized access attempts