Connect

Anti CSRF:

CSRF protection middleware.

This middleware adds a req.csrfToken() function to make a token
which should be added to requests which mutate
state, within a hidden form field, query-string etc. This
token is validated against the visitor's session.

The default value function checks req.body generated
by the bodyParser() middleware, req.query generated
by query(), and the "X-CSRF-Token" header field.

This middleware requires session support, thus should be added
somewhere below session() and cookieParser().

Options:

  • value a function accepting the request, returning the token

Source

module.exports = function csrf(options) {
  options = options || {};
  var value = options.value || defaultValue;

  return function(req, res, next){
    
    // already have one
    var secret = req.session._csrfSecret;
    if (secret) return createToken(secret);

    // generate secret
    uid(24, function(err, secret){
      if (err) return next(err);
      req.session._csrfSecret = secret;
      createToken(secret);
    });
    
    // generate the token
    function createToken(secret) {
      var token;

      // lazy-load token
      req.csrfToken = function csrfToken() {
        return token || (token = saltedToken(secret));
      };
      
      // compatibility with old middleware
      Object.defineProperty(req.session, '_csrf', {
        configurable: true,
        get: function() {
          console.warn('req.session._csrf is deprecated, use req.csrfToken() instead');
          return req.csrfToken();
        }
      });
      
      // ignore these methods
      if ('GET' == req.method || 'HEAD' == req.method || 'OPTIONS' == req.method) return next();
      
      // determine user-submitted value
      var val = value(req);
      
      // check
      if (!checkToken(val, secret)) return next(utils.error(403));
      
      next();
    }
  }
};

defaultValue()

Default value function, checking the req.body
and req.query for the CSRF token.

Source

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

saltedToken()

Return salted token.

Source

function saltedToken(secret) {
  return createToken(generateSalt(10), secret);
}

createToken()

Creates a CSRF token from a given salt and secret.

Source

function createToken(salt, secret) {
  return salt + crypto
    .createHash('sha1')
    .update(salt + secret)
    .digest('base64');
}

checkToken()

Checks if a given CSRF token matches the given secret.

Source

function checkToken(token, secret) {
  if ('string' != typeof token) return false;
  return token === createToken(token.slice(0, 10), secret);
}

generateSalt()

Generates a random salt, using a fast non-blocking PRNG (Math.random()).

Source

function generateSalt(length) {
  var i, r = [];
  for (i = 0; i < length; ++i) {
    r.push(SALTCHARS[Math.floor(Math.random() * SALTCHARS.length)]);
  }
  return r.join('');
}

var SALTCHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';