Express.js CSRF Protection

Cross-Site Request Forgery (CSRF) is a type of malicious attack where a web application is tricked into trusting a user's browser to transmit unauthorized commands. CSRF exploits the user's active session to perform unwanted actions on their behalf. This tutorial will guide you through implementing CSRF protection in your Express.js applications.



Understanding CSRF Attacks

CSRF attacks occur when a malicious website, email, or application causes a user's web browser to perform an unwanted action on a site where the user is authenticated. CSRF tricks authenticated users into submitting unwanted requests. These attacks can lead to serious consequences such as:

  • Changing user account details
  • Making purchases without consent
  • Deleting important data

How CSRF Protection Works

CSRF protection uses tokens to verify legitimate requests. It works by:

  1. Generating a CSRF token on the server.
  2. Embedding the token in every HTML form or AJAX request.
  3. Verifying the token on each state-changing request.

If the token is missing or incorrect, the server denies the request.

Setting Up CSRF Protection in Express.js

Express.js doesn't include CSRF protection by default. Use the csurf middleware to secure your application.

Step 1: Install Required Packages

npm install express cookie-parser csurf

Step 2: Basic Setup

Here's a simple Express app with CSRF protection:

// Import necessary modules
const express = require('express');
const cookieParser = require('cookie-parser');
const csrf = require('csurf');

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

// Use cookieParser middleware to read cookies from incoming requests
app.use(cookieParser());

// Use express.urlencoded middleware to parse URL-encoded form data (from POST forms)
app.use(express.urlencoded({ extended: true }));

// Set up csurf middleware to enable CSRF protection using cookies
const csrfProtection = csrf({ cookie: true });

// Register the CSRF protection middleware globally
app.use(csrfProtection);

// Route to display an HTML form
app.get('/form', (req, res) => {
  // req.csrfToken() generates a CSRF token for the current session
  // Embed this token in a hidden form field
  res.send(`
    <form action="/submit" method="POST">
      <input type="hidden" name="_csrf" value="${req.csrfToken()}">
      <input type="text" name="name" placeholder="Enter name">
      <button type="submit">Submit</button>
    </form>
  `);
});

// Route to handle form submission
app.post('/submit', (req, res) => {
  // If CSRF token is valid, request reaches here
  const name = req.body.name;
  res.send(`Hello, ${name}. CSRF token validated.`);
});

// Start the server
app.listen(port, () => {
  console.log(`App running at http://localhost:${port}`);
});

In this example, the form is returned directly as an HTML string using res.send(), which is suitable for basic learning and quick testing. In real-world applications, you should use a template engine like EJS, Pug, or Handlebars to render HTML views and pass the CSRF token using res.render() with <%= csrfToken %> or equivalent syntax.

Step 3: Handling CSRF Errors

Use error-handling middleware to catch CSRF token mismatches:

app.use((err, req, res, next) => {
  if (err.code === 'EBADCSRFTOKEN') {
    // CSRF token mismatch
    res.status(403).send('Invalid CSRF token.');
  } else {
    next(err);
  }
});

Best Practices for CSRF Protection

  • Use HTTPS: Prevent token sniffing during transmission.
  • Avoid GET for state changes: Use POST, PUT, or DELETE for such requests.
  • Regenerate tokens: Generate a new token for each session or form view.

Example with AJAX

To securely send AJAX requests, include the CSRF token in the request headers. If you're using EJS or another templating engine, pass the token from the server (e.g., using <%= csrfToken %>) and inject it into your JavaScript code.

<script>
  fetch('/submit', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'CSRF-Token': '<%= csrfToken %>' // Inject token using template engine
    },
    body: JSON.stringify({ name: 'Amit' })
  })
  .then(res => res.text())
  .then(data => console.log(data));
</script>

Enable JSON Parsing in Express

app.use(express.json());

The csurf middleware automatically checks the CSRF-Token header.

Conclusion

In this tutorial, you learned what CSRF attacks are and why they pose a threat to authenticated web applications. You understood how CSRF protection works using tokens and how to implement it in an Express.js app using the csurf middleware. You also learned how to handle CSRF errors, apply best practices like using HTTPS and proper HTTP methods, and how to secure AJAX requests by including the CSRF token in headers.



Found This Page Useful? Share It!
Get the Latest Tutorials and Updates
Join us on Telegram

Keep W3schools Growing with Your Support!
❤️ Support W3schools