Prevent Cross-Site Request Forgery in Express Apps with csurf

John Au-Yeung
Mar 15, 2020 · 5 min read
Photo by Diego Passadori on Unsplash

Cross-site request forgery (CSRF) is an attack where attackers send requests from unauthorized domains to our back end, doing malicious things.

To prevent this, we need to send a CSRF token to authorized users and check for the CSRF token in our requests.

In this article, we’ll look at how to do this with the csurf middleware.

Adding the Package

To use this package, we have use cookie-parser if we set the cookie option to a non-false value.

Otherwise, we have to use a session middleware like express-session or cookie-session before this module.

To install the package we run:

Options

The csurf package takes a variety of options and adds a req.csrfToken() function to make a new CSRF token.

cookie

The cookie option determines if the secret should be stored in a cookie or in req.session . This defaults to false .

When it’s set to true or an object of options for the cookie, then we can’t use req.session .

This means that we don’t have to use session middleware. Instead, we use cookie-parser middleware before this one.

The object for the cookie options can have the following properties:

  • key — the name of the cookie to use to store the token secret, which defaults to _csrf
  • path — the path of the cookie, which defaults to /
  • signed — indicates if the cookie should be signed, which defaults to false
  • secure — marks the cookie to be used with HTTPS only, defaults to false
  • maxAge — the number of seconds after which the cookie will expire
  • httpOnly — flags the cookie to be accessible only by the web server, defaults to false
  • sameSite — sets the same site policy for the cookie, defaults to none
  • domain — sets the domain the cookie is valid on, defaults to the current domain

ignoreMethods

An array of methods for which CSRF token check will be disabled, defaults to ['GET','HEAD','OPTIONS]

sessionKey

Determine what key the on req the session object will be location. The defaults to 'session' .

If the cookie option isn’t false , this option does nothing.

value

Provide a function the middleware will run to read the token from the request for validation.

The default value is a function that reads the token from the following locations in order:

  • req.body._csrf —typically generated by the body-parser module.
  • req.query._csrf — a built-in from Express.js to read from the URL query string.
  • req.headers['csrf-token'] — the CSRF-Token HTTP request header.
  • req.headers['xsrf-token'] — the XSRF-Token HTTP request header.
  • req.headers['x-csrf-token'] —the X-CSRF-Token HTTP request header.
  • req.headers['x-xsrf-token'] — the X-XSRF-Token HTTP request header.
Photo by kevin Londoño on Unsplash

Examples

A simple example for generating a CSRF token is as follows:

We just store the secret for the user in a cookie so we can use cookie-parser to parse the secret and sent it to the user.

Then we get something like:

as the response.

To use it, we pass it into a form as the value of a hidden field.

For example, we can use it as follows in index.js:

Then in the views folder, we add index.ejs and add:

The / route will render the index.ejs template with the csrfToken variable available in the template to interpolate the CSRF token.

In index.ejs , we’ll get the csrfToken and set it as the value. Then when we type in something and click Submit, then we get the name parsed in the process route, which shows us what we typed.

Without the CSRF token, we’ll get an invalid CSRF token error.

Ajax Example

We can use it for Ajax request by passing it into the CSRF-Token header.

For example, we can add the following for index.js :

Then in index.ejs , we can add the following:

The code above passes the CSRF token the same way as before, except that it goes to the meta tag instead of a hidden input. The only difference is that we get the form data and submit it via Ajax instead of a normal URL-encoded POST request.

The CSRF token is passed into the CSRF-Token header along with the Accept and Content-Type headers set to application/json so that we can submit a JSON request.

Then we stringify the JSON body so that we can pass it in.

Finally, we get back the response.

Conclusion

We can use the csurf middleware to prevent cross-site request forgeries.

It works by issuing a CSRF token and then passing it onto the client-side. Then when the client makes a request, then the csurf middleware checks the CSRF token to see if is request is allowed to proceed.

Once the CSRF token is checked to be valid, the request will be completed. Otherwise, an error will be returned.

DataSeries

Imagine the future of data

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store