CSRF protection in ExpressJS

From http://sporcic.org/2012/10/csrf-with-nodejs-and-express-3 :

app.use(express.csrf());
app.use(function(req, res, next){
    res.locals.token = req.session._csrf;
    next();
});
app.use(app.router);

      

To use the above protection, does this mean that I have to hide hidden input _csrf

on all my forms, including admin-only pages?

+1


source to share


2 answers


One option is to add a hidden input field to all of your forms, as you mentioned. But according to the Express docs on csrf:

The default value function checks req.body

generated by the middleware bodyParser()

, req.query

generated query()

, and the header field "X-CSRF-Token"

.

So, depending on your client side structure, you can also use query string or alternatives X-CSRF-Token

.

The point remains what you need:

  • pass the token _.csrf

    from Express to the client side
  • return the _.csrf

    client-side token back to Express in all your mutating states (POST / PUT / DELETE) so that Express can compare it with req.session._csrf

    to complete the loop.

For example, if your client-side is in Angular, the module $http

offers default csrf protection, looks for a named cookie XSRF-TOKEN

and returns that value in all state change requests (POST / PUT / DELETE) via a named header X-XSRF-TOKEN

. This is an unfortunate match because the name is different from the name of the header in which Express looks for it, that is, X-CSRF-Token

(notice -XSRF-

vs. -CSRF-

).



To overcome this you need

Step 1 . On the Express side, add the CSRF middleware default function to find the token value in the header X-XSRF-TOKEN

, in addition to all other default locations:

app.use(express.csrf({value: function(req) {
    var token = (req.body && req.body._csrf) || 
        (req.query && req.query._csrf) || 
        (req.headers['x-csrf-token']) || 
        // This is the only addition compared to the default value function
        (req.headers['x-xsrf-token']);
    return token;
    }
});

      

Step 2 . On the Express side, set the token value added by the CSRF middleware in again to the req.session._csrf

cookie that Angular will look for using the custom middleware:

app.use(function(req, res, next) {
    req.cookie('XSRF-TOKEN', req.session._csrf);
    next();
});

      

Angular will now find it and include it in the header X-XSRF-TOKEN

without any further action.

+7


source


Later in this article, the author explains that this provides a "token" property to all of your templates that need to be included in a hidden input field.

Notice the 2nd line in his jade example:



form(action='/form',method='post')
  input(type='hidden', name='_csrf', value=token)
  label(for='color') Color:
  input(type='text',name='color',size='50')
  button(type='submit') Save

      

0


source







All Articles