expressjs / csurf

CSRF token middleware
MIT License
2.3k stars 217 forks source link

I don't understand how this module works. #111

Closed miparnisari closed 7 years ago

miparnisari commented 7 years ago

Or rather, I don't know how to use it :)

Basically, I want the following: 1) When a user registers or logs into my app I want to set a header with an Anti-CSRF token. 2) When a user goes to any other route I want to verify this token.

So I set the following code into my server:

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
  extended: true
}));
app.use(cookieParser());
app.use(csrf({ cookie: true }));
app.use(function (req, res, next) {
  res.cookie('XSRF-TOKEN', req.csrfToken());
  next();
});

// unauthenticated routes
var authCtrl = require('./routes/auth');
app.use('/auth/login', authCtrl.login);
app.use('/auth/register', authCtrl.register);

// verify JWT token for authorization
app.use(require('./middleware/access_token').checkJwt);

// authenticated routes
var usersCtrl = require('./routes/user');
app.get('/users', node_acl.customMiddleware, usersCtrl.getAll);

// ... more routes ...

// global error handler
app.use(function (err, req, res, next) {
  console.error(err);
  if (err.code == 'EBADCSRFTOKEN') {
    err.status = 403;
    err.message = 'Invalid Anti-CSRF token.';
  }
  res.status(err.status || 500).send(err.message || 'Internal server error.');
});

The problem is the following: the line that goes app.use(csrf({ cookie: true })); already tries to validate the token. But I cannot remove it, because then this code req.csrfToken() would fail because csrfToken() is undefined.

Am I missing something here? How do I attach csrfToken() to req without actually trying to validate it?

dantman commented 7 years ago

CSRF tokens aren't tied to user auth, so there's no need to wait till post-login to set and verify the csrf token. In fact it's probably best to have csrf protection on your registration page so that 3rd party websites can't generate spam accounts while bypassing any ip filters you might implement by tricking the browsers of random visitors to their website to submit the registration request.

miparnisari commented 7 years ago

Okay, so would it be okay to issue a CSRF token on app launch? Say, on the .run() block of my Angular app?

dougwilson commented 7 years ago

Yea, that works. The purpose of CSRF as a protection is that there is a gap in the web that allows third-parties to make blind calls to any other web site. All pages that perform some kind of action should be protected by the CSRF token, including your user sign up form, and potentially even your user login form.

The req.csrfToken() should only ever be called on a page that displays a form (typically uses the GET method) and then the middleware will automatically validate any POST, PUT, etc. requests to make sure they have the token in them.