Pregunta

I am developing a simple web app using nodejs, express and when i switched to session and csrf, my PUT, DELETE and POST Requests are failing. with error:

error: Forbidden at Object.exports.error (appFolder/node_modules/express/node_modules/connect/lib/utils.js:63:13) at createToken (appFolder/node_modules/express/node_modules/connect/lib/middleware/csrf.js:82:55)

I looked at this line, and found that it calls checkToken function which calls the defaultValue which finds the csrf token in the request like this:

function defaultValue(req) {
  return (req.body && req.body._csrf)
    || (req.query && req.query._csrf)
    || (req.headers['x-csrf-token'])
    || (req.headers['x-xsrf-token']);

}

This was giving null or undefined value, and my checkToken was failing.

My PUT requests are generated by backbone and i just send the model's data. so i started sending back the token in cookie. I set the token in cookie like:

app.use(express.cookieParser());
app.use(express.session({
    secret: '6767678376-3hudh-2u78di90-kjdu39i-jfujd'
}));
app.use(function(req,res,next) {
    console.log("Body "  + JSON.stringify(req.headers));
    return next();
});
app.use(express.csrf());


app.use(express.static(path.join(__dirname, 'public')));

app.use(function(req, res, next) {
    console.log(req.body);
    res.cookie('x-csrf-token', req.csrfToken());
    console.log('CSRF : ' + req.csrfToken());
    //res.session._csrf = req.csrfToken();
    return next();
});

and changed the defaultValue(req) to

function defaultValue(req) {
  var csrf_token = (req.body && req.body._csrf)
    || (req.query && req.query._csrf)
    || (req.headers['x-csrf-token'])
    || (req.headers['x-xsrf-token']);
  if(csrf_token)
    return csrf_token;

  // find in cookie.
  if(!req.headers['cookie'])
    return undefined;

  var csrfTokenInCookie = (req.headers['cookie'].split('x-csrf-token='));
  if(csrfTokenInCookie && (csrfTokenInCookie.length == 2)) {
    return csrfTokenInCookie[1];
  }
  var xsrfTokenInCookie = (req.headers['cookie'].split('x-xsrf-token='));
  if(xsrfTokenInCookie && (xsrfTokenInCookie.length == 2)) {
    return xsrfTokenInCookie[1];
  }
}

Now defaultValue is giving the csrftoken token rightly, but again checkToken is failing.

The file is here: csrf.js

What am i doing wrong ?

Or how can it not generate back the right-token ?

¿Fue útil?

Solución

Your issue is with Express not sending the CSRF token back in a header for POST/PUT/DELETE requests. Express's CSRF middleware is doing the correct thing in rejecting these requests when the header is missing.

Here's info on adding the header you need in Backbone: How to protect against CSRF when using Backbone.js to post data?

Otros consejos

your trying to validate the cookie and express session these will be different tokens so it will fail you would have to choose one either the cookie or token.

the author mentions it here https://github.com/expressjs/csurf/issues/52

personally i would recommend disabling cookies altogether and pass the token through the headers and form body -- this worked for me.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top