csrf
Type: RequestHandler
Access: nauth.middleware.csrf
Express middleware that validates CSRF tokens for state-changing requests when using cookie-based token delivery.
Signature
nauth.middleware.csrf: RequestHandler
Overview
The csrf middleware validates CSRF tokens to prevent Cross-Site Request Forgery attacks. It uses lazy validation - errors are stored in request attributes and only thrown when requireAuth() is called.
Key Features:
- Validates CSRF token from header matches cookie value
- Skips safe HTTP methods (GET, HEAD, OPTIONS)
- Skips routes marked with
public()helper - Deferred validation until
requireAuth()is called - Only enforces for cookie-based token delivery
Usage
Mount Order
CSRF middleware must be mounted after clientInfo and before auth:
import express from 'express';
import { NAuth, ExpressAdapter } from '@nauth-toolkit/core';
const app = express();
const nauth = await NAuth.create({
config: authConfig,
dataSource,
adapter: new ExpressAdapter(),
});
// Mount order matters!
app.use(nauth.middleware.clientInfo); // 1st - Initializes context
app.use(nauth.middleware.csrf); // 2nd - CSRF validation
app.use(nauth.middleware.auth); // 3rd - JWT validation
app.use(nauth.middleware.tokenDelivery); // 4th - Token delivery
Configuration
CSRF middleware is automatically enabled when using cookie-based token delivery:
const nauth = await NAuth.create({
config: {
tokenDelivery: {
method: 'cookies', // CSRF middleware enabled
},
security: {
csrf: {
// Name of the CSRF header to check. Default: 'x-csrf-token'
headerName: 'x-csrf-token',
// Name of the CSRF cookie. Default: '<prefix>csrf_token'
cookieName: 'nauth_csrf_token',
// Length of CSRF token in bytes. Default: 32
tokenLength: 32,
// Paths that bypass CSRF validation entirely (prefix match)
excludedPaths: ['/webhook', '/public-api'],
// Cookie options for the CSRF token cookie
cookieOptions: {
secure: true, // HTTPS only. Set false for localhost
sameSite: 'strict', // 'strict' | 'lax' | 'none'
domain: undefined, // e.g. '.example.com' for subdomain sharing
path: '/',
priority: 'high', // 'low' | 'medium' | 'high'
},
},
},
},
dataSource,
adapter: new ExpressAdapter(),
});
excludedPaths uses a prefix match (String.prototype.startsWith). A path of /webhook will match /webhook, /webhook/stripe, etc.
Behavior
- Validates
x-csrf-tokenheader against cookie value - Skips GET, HEAD, OPTIONS requests (safe methods)
- Skips routes marked with
public()helper - Stores errors in
req.attributes.nauthCsrfError(lazy validation) - Only enforces for cookie-based token delivery
Frontend Integration
Frontend must send CSRF token in headers:
// Read CSRF token from cookie
const csrfToken = getCookie('nauth_csrf_token');
// Send in header for POST/PUT/DELETE/PATCH
fetch('/api/action', {
method: 'POST',
headers: {
'x-csrf-token': csrfToken,
},
body: JSON.stringify({ data: 'value' }),
});
Errors
CSRF errors are stored in request attributes and thrown by requireAuth():
| Code | When | Details |
|---|---|---|
CSRF_TOKEN_MISSING | Token missing in header or cookie | undefined |
CSRF_TOKEN_INVALID | Token mismatch | undefined |
Related APIs
- public() - Bypass CSRF validation
- requireAuth() - Enforce CSRF validation
- Auth Middleware - JWT validation
- CsrfService - CSRF token generation