Protecting Routes and APIs
Learn how to protect routes and APIs with Wristband auth middleware.
Most backend server auth SDKs include auth middleware that protects the routes and APIs that require an authenticated user. Your application creates the auth middleware from the SDK instance and applies it to the routes it should protect. On each request to a protected route, the middleware authenticates the request before the route handler runs, and rejects the request if it can't.
How the auth middleware plugs into your application follows your framework's conventions. Depending on the SDK, it's a middleware function, a guard, a dependency, a decorator, or an authorization policy, but it behaves the same way in each.
For example, using the Express Auth SDK:
// src/wristband.ts
export const requireWristbandAuth = wristbandAuth.createAuthMiddleware({
authStrategies: ['SESSION'],
sessionConfig: {
sessionOptions: {
secrets: process.env.SESSION_SECRET!,
},
},
});// src/routes/protected-routes.ts
import { requireWristbandAuth } from '../wristband';
app.get('/api/orders', requireWristbandAuth, (req, res) => {
res.status(200).json({ orders: [] });
});Routes without the auth middleware aren't protected. The session is still available in them, but nothing checks whether the user is authenticated.
Authentication Strategies
The auth middleware authenticates requests using one or more authentication strategies:
| Strategy | Authenticates With | Typical Use |
|---|---|---|
SESSION | The session cookie | Requests from your own frontend, following the Backend Server Integration Pattern. |
JWT | A Bearer token in the Authorization header | Requests that send an access token directly, such as from a frontend using the Token Endpoint, another service, or a mobile app. |
Most SDKs support both strategies. Some only support the SESSION strategy.
Session Strategy
When the auth middleware uses the SESSION strategy, it performs the following steps on each request:
- Validates the session: Checks that the session belongs to an authenticated user (
isAuthenticatedistrue). - Validates the CSRF token: If CSRF protection is enabled, checks that the CSRF token in the request header matches the one in the session.
- Refreshes the access token: If the session contains a refresh token and the access token has expired, gets new tokens from Wristband and updates the session.
- Saves the session: Writes the session back to the session cookie, which keeps the session rolling and persists any refreshed tokens.
The route handler then runs with the session available, including any refreshed tokens.
See Token Refresh for more on how tokens are refreshed, and CSRF Protection for more on CSRF validation.
JWT Strategy
When the auth middleware uses the JWT strategy, it performs the following steps on each request:
- Extracts the Bearer token: Reads the access token from the
Authorization: Bearer <token>request header. - Validates the token: Verifies the token's signature using the signing keys from Wristband's JWKS endpoint, and checks its claims, such as its expiration and issuer. The signing keys are cached in memory after they're first fetched.
- Exposes the token payload: Makes the decoded token payload and the raw token available to the route handler.
The JWT strategy doesn't use the session. It doesn't refresh tokens, validate CSRF tokens, or save anything, so the client sending the request is responsible for keeping its access token valid.
For example, using the Express Auth SDK, which exposes the payload on req.auth:
// src/wristband.ts
export const requireWristbandAuth = wristbandAuth.createAuthMiddleware({
authStrategies: ['JWT'],
});app.get('/api/orders', requireWristbandAuth, (req, res) => {
const userId = req.auth.sub;
res.status(200).json({ userId, orders: [] });
});See JWT Validation for more on how access tokens are validated.
Using Multiple Strategies
The auth middleware can try more than one strategy. It tries them in the order you provide, and the request is authenticated as soon as one strategy succeeds. This lets the same route accept requests from your own frontend with a session cookie, and from other clients with a Bearer token.
For example, using the Express Auth SDK:
export const requireWristbandAuth = wristbandAuth.createAuthMiddleware({
// Try the session cookie first, then fall back to a Bearer token.
authStrategies: ['SESSION', 'JWT'],
sessionConfig: {
sessionOptions: {
secrets: process.env.SESSION_SECRET!,
},
},
});Unauthenticated Requests
When no strategy can authenticate a request, the auth middleware rejects it before the route handler runs. For API routes, most SDKs respond with an HTTP status code that tells your frontend why:
| Status Code | When It Occurs |
|---|---|
401 Unauthorized | No valid session or Bearer token was found, or the access token couldn't be refreshed. |
403 Forbidden | The CSRF token was missing or didn't match. |
500 Internal Server Error | An unexpected error occurred while authenticating the request. |
Your frontend is responsible for handling these responses, typically by sending the user to your Login Endpoint.
Some SDKs also protect server-rendered pages (e.g. Next.js App Router). For a protected page, the auth middleware redirects the user to your Login Endpoint instead.
Protecting the Session and Token Endpoints
Your Session and Token Endpoints must always be protected by the auth middleware with the SESSION strategy. The middleware makes sure the user is authenticated before the endpoint returns their session data or access token, and refreshes the access token first if it has expired. These responses must never be cached, and most SDKs set the Cache-Control: no-store and Pragma: no-cache headers automatically when the middleware saves the session.
See Auth Endpoints for more on the Session and Token Endpoints.
Auth Middleware Configuration
Setting names and defaults vary by SDK.
| Setting | Required | Default | Description |
|---|---|---|---|
| Authentication strategies | Yes | N/A | The strategies to try, in order: SESSION, JWT, or both. |
| Session options | Only with the SESSION strategy | N/A | The same session options your application uses for session management. |
| CSRF header name | No | X-CSRF-TOKEN | The request header the middleware reads the CSRF token from. Only used when CSRF protection is enabled. |
| JWKS cache size | No | 20 | The maximum number of signing keys cached in memory. Only used with the JWT strategy. |
| JWKS cache lifetime | No | No expiration | How long signing keys stay cached before they're fetched again. Only used with the JWT strategy. |
See the Session Configuration section of Session Management for the available session options, and the JWT Validation SDK Configuration section of JWT Validation for the available JWT validation options.
Updated about 4 hours ago