sofi-csrf
v1.0.1
Published
Fast, fully-typed, and framework-agnostic CSRF protection library for Node.js. Works with Express and Hono.
Maintainers
Readme
Sofi CSRF
A fast, fully-typed, and framework-agnostic CSRF (Cross-Site Request Forgery) protection library tailored for Node.js. It features a standalone Core logic engine with an out-of-the-box adapter specifically designed for Express.js.
Features
- Framework-Agnostic Core: Secure payload generator and timing-safe verification extracted from the routing logic. Fits any HTTP node server.
- TypeScript First: End-to-end typed classes and functions properly documented with
TSDoc. - Express Adapter: Pre-packaged middleware wrapping
req,resand cookies appropriately to effortlessly handle injection and error throwing. - Token Rotation: Avoid token reuse attacks with the out-of-the-box regeneration middlewares.
Supported Frameworks & Contributing
Currently, sofi-csrf provides official "out-of-the-box" adapters for:
- Express.js
- Hono
Thanks to its framework-agnostic core engine, we welcome community PRs! Feel free to contribute by creating new adapters (Fastify, Koa, NestJS, etc.) to expand the ecosystem. Likewise, I will be adding more official adapters progressively as time permits.
Installation
npm install sofi-csrf(Note for Express adapter: You should also use cookie-parser within your Express application).
Usage Guide (Express)
import express from 'express';
// Note: [cookie-parser](https://www.npmjs.com/package/cookie-parser) is required to extract cookies smoothly before this middleware
import cookieParser from 'cookie-parser';
import { expressCsrf } from 'sofi-csrf';
const app = express();
app.use(express.json());
app.use(cookieParser());
// 1. Initialize the middleware adapter (Accepts partial options)
const { csrfMiddleware, verifyCsrfToken, regenerateCsrfToken } = expressCsrf({
cookieName: 'xsrf-token', // Defaults to 'csrfToken'
cookieOptions: {
secure: process.env.NODE_ENV === 'production',
httpOnly: true,
maxAge: 3600000
}
});
// 2. Inject tokens globally (assigns token to local cookies, req and res.locals)
app.use(csrfMiddleware);
// 3. Retrieve token for frontend binding or views
app.get('/form', (req, res) => {
// Can be easily retrieved from req.csrfToken, or res.locals.csrfToken inside EJS/Pug templates!
res.json({ csrfToken: req.csrfToken });
});
// 4. Secure your data mutations routes
// Client must send the token either in req.body._csrf OR headers['x-csrf-token']
app.post('/submit', verifyCsrfToken, (req, res) => {
res.json({ message: "Successfully executed operation with valid token" });
});
// 5. Rotate the token
// Often necessary when performing high privilege or session-upgrade tasks
app.post('/sensitive-update', regenerateCsrfToken, (req, res) => {
res.json({ message: "Task completed securely. A new token has rolled.", newToken: req.csrfToken });
});Usage Guide (Hono)
import { Hono } from 'hono';
import { honoCsrf } from 'sofi-csrf';
const app = new Hono();
// 1. Initialize the adapter
const { csrfMiddleware, verifyCsrfToken, regenerateCsrfToken } = honoCsrf({
cookieName: 'xsrf-token',
});
// 2. Inject token in cookies and set it in context variables (c.get('csrfToken'))
app.use('*', csrfMiddleware);
// 3. Simple retrieval
app.get('/form', (c) => {
return c.json({ token: c.get('csrfToken') });
});
// 4. Secure data mutations, accepts 'x-csrf-token' header or '_csrf' in body
app.post('/submit', verifyCsrfToken, (c) => {
return c.text('Processed securely');
});
// 5. Native Token Rotation
app.post('/rotate', regenerateCsrfToken, (c) => {
return c.json({ message: "Rotated successfully", newToken: c.get('csrfToken') });
});API Documentation
Explore the code using IDE intelligence to enjoy detailed TSDocs snippets and rich context.
Built-In Interfaces
CsrfCore: Handpicks the algorithm validations.CsrfOptionsanddefaultOptions: Handle customizable rules.CsrfForbiddenError: Default thrown exception containing the403status.
Options Configuration
When initializing your adapter (e.g., expressCsrf() or honoCsrf()), you can pass an optional configuration object to override the defaultOptions.
Below is the exhaustive list of options you can configure:
| Option | Type | Default Value | Description |
| :--- | :--- | :--- | :--- |
| cookieName | string | 'csrfToken' | The name of the cookie where the generated token is stored. |
| tokenLength | number | 24 | Cryptographic byte length for generation (produces a 48 hexadecimal character string). |
| cookieOptions.httpOnly | boolean | true | Prevents client-side scripts from accessing the cookie via document.cookie. |
| cookieOptions.secure | boolean | false | Whether to ensure the cookie is only sent over HTTPS (Highly recommended to set to true in production). |
| cookieOptions.maxAge | number | 3600000 (1 hour) | Expiration time for the cookie in milliseconds. |
Support
If you found this library helpful, consider supporting my work!
