Auth Proxy Configuration
The createAuthProxy function creates a Next.js proxy that handles all authentication logic. This page covers all configuration options.
Basic Setup#
Configuration Options#
apiBaseUrl#
Required - Your backend API base URL.
cookies#
Required - Cookie configuration for token storage.
Dual-token mode is enabled simply by naming a
refreshcookie. Theusercookie becomes a short-lived access token and therefreshcookie a separate, long-lived token sent only to the refresh endpoint. See Token Management.
endpoints#
Backend endpoints for auth operations. All paths are relative to apiBaseUrl.
guestToken#
Configure guest token behavior.
access#
Route access control configuration.
i18n#
Internationalization support. Extracts locale from URL path and sets x-locale header for downstream route handlers.
How it works:
- User visits
/tr/blog - Proxy extracts
trfrom the first path segment - Sets
x-locale: trresponse header (accessible viaheaders().get('x-locale')) - Route handlers can read this header
- API client automatically appends
?lang=trto backend requests
See the i18n documentation for full setup guide.
excludedPaths#
Paths to skip proxy entirely.
blockBrowserApiAccess#
Block direct browser access to API routes.
When enabled, requests with Accept: text/html to /api/* are redirected to /.
responseMappers#
Custom parsers for different backend response formats.
refresh#
Token refresh behaviour — concurrency, proactive renewal, and reuse detection
(RFC 9700). All fields are optional, but concurrent-refresh single-flight is
enabled by default (refresh.singleFlight: true); set
refresh.singleFlight: false to restore independent per-request refreshes.
On a detected reuse — or when access.guestFallbackOnUserRefreshFail is
false — the proxy clears every auth cookie and redirects to login (or returns
401 for API routes). It never silently downgrades to a guest session.
refresh.store
singleFlight coalesces concurrent refreshes inside one runtime instance. A
store extends that: when another instance has just rotated the same token, its
result is reused instead of issuing a second refresh that a backend with reuse
detection would flag as theft.
Keys are SHA-256 hashes of the old token, never the token itself. Values hold
freshly issued tokens for storeTtlMs, so back the store with a secured service
and keep the TTL small. Only a refreshed token that passes validation is stored.
Stale entries fall through to a normal refresh, and store errors are reported via
onError without failing the request.
Scope note:
refresh.storeis best-effort, not a distributed mutex —getandsetare not atomic, so two instances that miss the store at the same moment still refresh independently. Single-flight coalescing and local verification act per runtime instance: PM2 cluster workers, Passenger, Docker replicas and serverless/edge isolates each keep their own map. For full coverage, pair either mechanism with idempotent refresh handling on the backend — a rotation grace window, and acceptance of the previousjtifor that window, chosen larger than your refresh latency.
validate#
Token validation strategy. By default (mode: 'backend') the proxy validates
the token against endpoints.validate on every request. mode: 'local'
verifies the JWT in-process, restoring stateless auth and removing the
per-request backend roundtrip.
Local mode verifies JWT access tokens. Supply
validate.verifyfor asymmetric algorithms (RS256 / ES256) or JWKS key rotation.
authApi#
Which auth API routes the proxy skips entirely. Bypassed paths get no token validation, refresh, single-flight, proactive renewal or reuse detection.
The default is:
Keep the login and register routes listed — they carry no token yet — and keep the refresh route listed, since validating it would rotate the token before the route itself runs.
/api/auth/me is the interesting one. It is the route
AuthProvider polls, and while it is bypassed an
expired token simply returns 401 there. Removing it from the list routes it
through the normal pipeline: a single refresh runs, the new token is written to
the cookie and forwarded downstream via x-refreshed-token, and the route
returns 200 — no client-side 401 handling required.
csrf#
CSRF protection configuration.
rateLimit#
Rate limiting configuration.
audit#
Audit logging configuration.
onError#
Global error handler.
beforeAuth#
Hook that runs before auth validation.
afterAuth#
Hook that runs after auth validation.