Protecting Routes with Middleware
The Descope Next.js SDK provides authentication middleware to enforce secure access control across application routes. Middleware allows authentication checks before requests reach a page or API, ensuring only authorized users can proceed.
Although the middleware isn't strictly required, it is recommended for consistent and secure route protection.
This guide covers:
- Configuring authentication middleware
- Defining public and private routes
- Using wildcard paths for flexible route protection
- Redirecting unauthenticated users
- Handling session expiration and forced re-authentication
Setting Up Authentication Middleware
In Next.js, middleware intercepts requests before they reach a route. The Descope SDK provides authMiddleware()
to enforce authentication for protected pages.
Creating Middleware
Create a middleware.ts
file in the root of your Next.js project.
How Middleware and the SDK Works
- All routes are private by default.
- Public routes are explicitly defined using
publicRoutes
. - Private routes can be defined using
privateRoutes
, but if bothpublicRoutes
andprivateRoutes
are used,privateRoutes
is ignored. - Middleware redirects unauthenticated users to
redirectUrl
.
The Session Header
When a request is processed, the middleware:
- Extracts the session JWT from the request (
Authorization
header orDS
cookie). - Validates the JWT using Descope's backend.
- Encodes session data as a Base64 JSON string.
- Attaches the session data to the request headers under the
X-Descope-Session
header.
After validation, the middleware modifies the request headers to include the session data before forwarding the request.
This allows server-side components and API routes to access authentication details without manually validating the session again.
Session Storage Differences Between Next.js and React/JS
By default, the Descope Next.js SDK stores the DS (Descope Session) in a cookie, whereas the Web JS SDK and React SDK store it in localStorage. This means:
-
Next.js SDK (cookies):
- Accessible via JavaScript.
- Stored securely in a secure,
samesite=lax
cookie. - Automatically included in server-side requests.
- Persistent across browser sessions.
-
React SDK (local storage):
- Accessible via JavaScript.
- Requires manual handling for secure transmission to the backend.
Note
For more information on configuring the AuthProvider
, including options like adjusting the SameSite
cookie settings, refer to our Auth Provider documentation
This allows client-side applications to use the token for making authenticated API requests.
Multi-Project SDK Support
Descope's Next.js SDK supports multi-project setups, where each tenant in a multi-tenant application is mapped to a separate Descope project. This approach is ideal when tenants need isolated configurations or dedicated user stores.
A typical setup looks like this:
- Each request includes a header (e.g.,
x-tenant-id
) that identifies the tenant. - The application dynamically initializes the Descope SDK using the project ID associated with the tenant.
- Middleware handles authentication using the appropriate project.
SDK Instance Caching
To support multi-tenant applications efficiently, the SDK automatically caches instances based on project ID:
- On the first request for a given project ID, a new SDK instance is created.
- On subsequent requests with the same project ID, the existing instance is reused.
This per-project caching ensures optimal performance by avoiding redundant SDK initializations while allowing different tenants to use separate Descope configurations.
Note
Per-project configuration extends to Next.js SDK functions like session()
. When assigning a separate project to each tenant, the SDK automatically inherits the appropriate project settings, ensuring consistent authentication across your application.
Example: Tenant-Based Authentication
Here's a complete example showing how to implement tenant-based authentication in your middleware:
Using Wildcard Paths for Route Protection
Wildcard paths (*
) simplify route protection by applying authentication requirements to entire sections of an application.
Protecting API Endpoints
Protecting an Admin Section
Redirecting Unauthenticated Users
By default, unauthenticated users are redirected to /sign-in
. To customize this behavior, update redirectUrl
.
Redirecting to a Custom Login Page
Controlling Log Levels in the Descope Next.js SDK
The Descope Next.js SDK allows you to control logging levels for debugging and monitoring authentication-related events. This is useful for diagnosing issues during development and ensuring secure authentication flows in production.
Supported Log Levels
The logLevel
option in authMiddleware()
can be set to one of the following values:
Log Level | Description |
---|---|
debug | Logs detailed debug messages, useful for troubleshooting authentication flows. |
info | Logs general informational messages, such as successful logins and token validations. |
warn | Logs warnings about potential misconfigurations or non-critical issues. |
error | Logs only critical authentication failures and errors. |
Configuring Log Levels
You can set the log level when defining your middleware:
Example: Debugging Authentication
Setting the log level to debug
provides detailed output in the console, helping to trace authentication issues.
Sample Debug Logs
When logLevel: 'debug'
is set, you might see logs like:
If an error occurs:
Recommended Log Levels
- Development: Use
debug
orinfo
to get detailed logs while debugging authentication. - Production: Use
warn
orerror
to log only critical authentication failures.
For full implementation details, check the sample projects: