Cross-site request forgery (CRSF) is an attack that tricks the victim into executing malicious actions on a web application in which they are authenticated. Connect/Express comes packaged with a Cross-site request forgery protection middleware. This middleware allows us to ensure that a request to a mutate state is from a valid source. The CRSF middleware creates a token that is stored in the requests session as _csrf
. A request to our Express server will then need to pass the token in the header field X-CSRF-Token
.
Let's create a security ./lib/security/index.js
module that adds the csrf
middleware to our application. We define a function, Security
, that takes an Express app
as an argument and removes the middleware when in TEST
or COVERAGE
mode.
var express = require('express'), function Security(app) { if (process.env['NODE_ENV'] === "TEST" ||process.env['NODE_ENV'] === "COVERAGE") return; app.use(express.csrf()); }; module.exports = Security;
Let's make a change to our Express server ./lib/express/index.js
. The crsf
middleware requires session support, so we add the following line below the session
and passport
middleware:
require('../security')(app);
As we are using backbone.js
that uses jQuery under the hood to make AJAX requests, we will need to make a change to our backbone code ./public/components/vision/vision.js
. We will now override the Backbone.sync
function, so that all requests through it pass the X-CSRF-Token
in the header. The X-CSRF-Token
is pulled from a meta
tag in the master page:
Backbone.sync = (function(original) { return function(method, model, options) { options.beforeSend = function(xhr) { var token = $("meta[name='csrf-token']").attr('content'), xhr.setRequestHeader('X-CSRF-Token', token); }; original(method, model, options); }; })(Backbone.sync);
We now need to pass the X-CSRF-Token
to our master page via the master page route. The token is stored in the requests session as _csrf
, in the following code we add the token to csrftoken
in our view object:
exports.index = function(req, res){
var model = {
title: 'vision.',
description: 'a project based dashboard for github',
author: 'airasoul',
user: req.isAuthenticated() ? req.user.displayName : '',
csrftoken: req.session._csrf
};
res.render('index', model);
};
The csrftoken
is rendered in our master page in a meta
tag called csrf-token
; the backbone sync method will put it from this meta tag:
<meta name="csrf-token" content="{{csrftoken}}">
3.144.254.111