npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

csrf-protector

v1.0.0

Published

Robust CSRF protection for Node.js applications with support for stateful and stateless approaches

Readme

secure-csrf

npm version License: MIT

A robust, modern CSRF protection library for Node.js applications with zero dependencies. The package supports both stateful and stateless approaches to CSRF protection, making it flexible for various application architectures.

Features

  • 🔐 Strong security: Uses cryptographically secure token generation
  • 🧱 Zero dependencies: No external packages required
  • 🔄 Multiple modes: Support for both stateful (session-based) and stateless (cookie-based) approaches
  • 🔄 Secret rotation: Advanced protection with automatic secret rotation
  • 🚀 TypeScript support: Full TypeScript definitions included
  • 📦 Framework support: First-class Express.js integration with extensibility for other frameworks
  • 📝 Well-documented: Comprehensive documentation and examples

Installation

npm install secure-csrf

or

yarn add secure-csrf

Quick Start

Express.js Integration

const express = require('express');
const session = require('express-session');
const { expressMiddleware } = require('secure-csrf');

const app = express();

// Setup session middleware (required for stateful mode)
app.use(session({
  secret: 'your-session-secret',
  resave: false,
  saveUninitialized: false,
  cookie: { secure: process.env.NODE_ENV === 'production' }
}));

// Parse request bodies
app.use(express.urlencoded({ extended: false }));
app.use(express.json());

// Add CSRF protection
app.use(expressMiddleware());

// Routes
app.get('/', (req, res) => {
  // Pass the CSRF token to your template
  res.render('form', { csrfToken: req.csrfToken() });
});

app.post('/submit', (req, res) => {
  // The request has already been validated by the CSRF middleware
  res.send('Form submitted successfully!');
});

app.listen(3000, () => {
  console.log('Server running on port 3000');
});

In your HTML form

<form action="/submit" method="post">
  <input type="hidden" name="_csrf" value="<%= csrfToken %>">
  <input type="text" name="name" placeholder="Your name">
  <button type="submit">Submit</button>
</form>

With AJAX requests

// Get the CSRF token from a meta tag, for example
const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');

fetch('/api/data', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-CSRF-Token': csrfToken  // Send the token in a header
  },
  body: JSON.stringify({ key: 'value' })
})
.then(response => response.json())
.then(data => console.log(data));

Usage Modes

Stateful Mode (Default)

In stateful mode, the CSRF secret is stored in the user's session. This is the most secure approach but requires a session management system.

const { expressMiddleware } = require('secure-csrf');

app.use(expressMiddleware({
  mode: 'stateful',  // This is the default
  sessionKey: 'csrfSecret'  // The key used to store the secret in the session
}));

Stateless Mode

In stateless mode, the CSRF secret is stored in a cookie. This approach doesn't require server-side session storage but provides slightly less security.

const { expressMiddleware } = require('secure-csrf');

app.use(expressMiddleware({
  mode: 'stateless',
  cookie: {
    secure: true,  // Only send over HTTPS
    httpOnly: true,  // Not accessible via JavaScript
    sameSite: 'strict',  // Stricter CSRF protection
    maxAge: 3600  // 1 hour in seconds
  }
}));

Security Considerations

Stateful vs. Stateless Approaches

Stateful (Synchronizer Token Pattern):

  • Token is generated on the server and stored in the session
  • Client receives a copy of the token to include in future requests
  • Provides stronger security as the secret never leaves the server
  • Requires session storage on the server

Stateless (Double Submit Cookie Pattern):

  • Secret is stored in a cookie
  • Token is generated using this secret and sent to the client
  • On subsequent requests, both the cookie and token are validated
  • No server-side session storage required
  • Slightly less secure than the stateful approach

Secret Rotation

For advanced security, you can enable automatic secret rotation:

const { expressMiddleware } = require('secure-csrf');

app.use(expressMiddleware({
  secretRotation: {
    enabled: true,
    interval: 3600000,  // Rotate secrets every hour (in milliseconds)
    maxSecrets: 2       // Keep 2 most recent secrets (to validate existing tokens)
  }
}));

Security Best Practices

  1. Use HTTPS: Always use HTTPS in production to protect cookies and headers from eavesdropping.

  2. Set Secure Cookies: Use the secure and httpOnly flags on cookies to enhance security.

  3. Use SameSite Cookies: The sameSite attribute helps prevent CSRF in modern browsers.

  4. Implement Secret Rotation: Regularly rotating secrets limits the window of opportunity for attackers.

  5. Protect All Sensitive Actions: Apply CSRF protection to all state-changing operations, not just forms.

API Reference

Core Module

SecureCsrf

The main class providing CSRF protection functionality.

import { SecureCsrf, CsrfMode } from 'secure-csrf';

const csrf = new SecureCsrf({
  mode: CsrfMode.STATEFUL,
  tokenLength: 32,
  // other options...
});

Methods:

  • generateSecret(length?: number): string - Generate a secure random secret
  • generateSecretAsync(length?: number): Promise<string> - Generate a secret asynchronously
  • createToken(secret?: string, data?: string): CsrfToken - Create a new CSRF token
  • verifyToken(token: string, secret?: string): boolean - Verify a CSRF token
  • rotateSecret(newSecret?: string): void - Rotate the secret
  • destroy(): void - Clean up resources (e.g., secret rotation timer)

Express Middleware

import { expressMiddleware } from 'secure-csrf';

app.use(expressMiddleware({
  // options...
}));

Options:

  • mode: CSRF protection mode ('stateful' or 'stateless')
  • cookieName: Name of the cookie (default: '_csrf')
  • headerName: Name of the header (default: 'x-csrf-token')
  • fieldName: Name of the form field (default: '_csrf')
  • sessionKey: Session key for storing the secret (default: 'csrfSecret')
  • ignoredRoutes: Routes to ignore (default: [])
  • ignoredMethods: HTTP methods to ignore (default: ['GET', 'HEAD', 'OPTIONS'])
  • cookie: Cookie options for stateless mode
  • secretRotation: Secret rotation settings
  • getToken: Custom function to extract token from request
  • onError: Custom error handler

Advanced Usage

Custom Token Extraction

app.use(expressMiddleware({
  getToken: (req) => {
    // Custom logic to extract token from request
    return req.headers['my-custom-header'] || req.body.myCustomField;
  }
}));

Custom Error Handling

app.use(expressMiddleware({
  onError: (err, req, res, next) => {
    // Custom error handling
    res.status(403).json({
      error: 'CSRF validation failed',
      message: err.message,
      code: 'CSRF_ERROR'
    });
  }
}));

Ignoring Specific Routes

app.use(expressMiddleware({
  ignoredRoutes: [
    '/webhook',  // Exact match
    /^\/api\/public\//  // RegExp pattern
  ]
}));

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the MIT License - see the LICENSE file for details.


Developed with ❤️ for the Node.js community.