CSRF Sync

4.2.1 · active · verified Sun Apr 19

CSRF Sync is a utility package designed to provide robust stateful Cross-Site Request Forgery (CSRF) protection for Express applications, utilizing the Synchroniser Token Pattern. Developed in response to the deprecation of `csurf` and the perceived complexity or limited scope of alternative solutions, `csrf-sync` (current stable version 4.2.1) aims for a targeted and simplified implementation. It requires a server-side session management middleware like `express-session` to store tokens. The library focuses on providing the essential components for CSRF protection without imposing a full solution, allowing developers to integrate it flexibly. It is actively maintained with regular updates and follows a clear versioning strategy, with significant changes typically highlighted in major version bumps.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates setting up an Express application with `express-session` and `csrf-sync` to protect a form submission route. It shows how to initialize the CSRF protection, generate a token, include it in an HTML form, and handle POST requests with CSRF validation, including basic error handling for invalid tokens.

import express from 'express';
import session from 'express-session';
import { csrfSync } from 'csrf-sync';

const app = express();
const port = 3000;

// Configure express-session middleware
app.use(session({
  secret: process.env.SESSION_SECRET ?? 'super-secret-key-please-change-me',
  resave: false,
  saveUninitialized: true,
  cookie: { httpOnly: true, secure: process.env.NODE_ENV === 'production' }
}));

// Initialize csrf-sync and get the protection middleware and token generator
const { csrfSynchronisedProtection, generateToken } = csrfSync();

// Apply CSRF protection to all routes (or specific ones)
app.use(csrfSynchronisedProtection);

// Middleware to parse URL-encoded bodies for form submissions
app.use(express.urlencoded({ extended: false }));

// Route to display a form with a CSRF token
app.get('/', (req, res) => {
  const token = generateToken(req);
  res.send(`
    <!DOCTYPE html>
    <html>
    <head><title>CSRF Test</title></head>
    <body>
      <h1>Submit Form</h1>
      <form action="/submit" method="POST">
        <input type="hidden" name="_csrf" value="${token}">
        <input type="text" name="data" placeholder="Enter data">
        <button type="submit">Submit</button>
      </form>
    </body>
    </html>
  `);
});

// Protected route to handle form submission
app.post('/submit', (req, res) => {
  res.send(`Data received: ${req.body.data} (CSRF protected)`);
});

// Error handling for CSRF issues (optional but recommended)
app.use((err, req, res, next) => {
  if (err.code === 'EBADCSRFTOKEN') {
    res.status(403).send('Invalid CSRF token - potential attack!');
  } else {
    next(err);
  } 
});

app.listen(port, () => {
  console.log(`Server listening at http://localhost:${port}`);
  if (!process.env.SESSION_SECRET) {
    console.warn('WARNING: SESSION_SECRET is not set. Using a default, which is insecure for production.');
  }
});

view raw JSON →