Dependency

The version of express is 4.10.6. When this note was made, I still found many code samples for express 3. So I guess this note would also to be deprecated soon.

Reference

CSRF

// dependency
{
  "dependencies": {
    "csurf": "^1.6.5"
  }
}

// routes
app.use(csrf());
app.use(function(req, res, next) {
  var token = req.csrfToken();

  // for jade
  res.locals.csrfToken = token;
  // for Angularjs
  res.cookie('XSRF-TOKEN', token);

  next();
});
app.use(function(err, req, res, next) {
  // called if there are errors.
  if (err.code !== "EBADCSRFTOKEN") {
    return next(err);
  }

  // handle CSRF token errors here
  res.status(403);
  res.send("leave me alone~~");

  console.log("bad csrf token");
});

In forms with method “POST”, set a hidden field with name “_csrf”:

form(method="post", action="/csrf")
  input(type="hidden", name="_csrf", value="#{ csrfToken }")

Angularjs read cookie ‘XSRF-TOKEN’ and send it back in header. Extra works are needed for jQuery.

html
  head
    meta(name="csrf-token", content="#{ csrfToken }")

    script.
      $(document).ready(function (e) {
        $.ajaxPrefilter(function(options, _, xhr) {
          if (!xhr.crossDomain) {
            var token = $('meta[name="csrf-token"]').attr('content');

            xhr.setRequestHeader("X-CSRF-Token", token);
          }
        });
      });

Note: Why setRequestHeader for jQuery

In most cases, setting _csrf in data field when post via ajax is enough. The problem surfaces when uploading files with “multipart/form-data”. If multiparty is used to handling file uploading, csrf checking happens before form processing which fails every time, because bodyparser ignore multipart form.

Expose Less Information to Attackers

var app = express();

// Disable the useless header "x-powered-by" whose value is "Express".
app.disable("x-powered-by");

// The default session cookie key of express is "connect.sid", change it.
// Secure cookie send session via https only.
// express session always set session a httponly cookie.
app.use(session({
  secret: "do not touch me",
  key: "session_id",
  cookie: {
    secure: true
  }
}));