Backbone.js handles posting data to server under the hood, so there is no easy way to insert a CSRF token in the payload. How can I protect my site against CSRF in this situation?
In this SO answer: https://stackoverflow.com/a/10386412/954376, the suggestion is to verify the x-Requested-By header to be XMLHTTPRequest. Is this enough to block all CSRF attempts?
In Django docs, the suggestion is to add CSRF token in another custom header in every AJAX request: https://docs.djangoproject.com/en/1.5/ref/contrib/csrf/#ajax. Is this necessary?
I understand if the attack uses hidden form, I am safe by just assuring the request is from XMLHTTPRequest. But is there any CSRF attack tricks that can forge the header?
Setting a global CSRF-token for all jQuery.ajax calls:
$(function(){
$.ajaxSetup({
headers: {'X-CSRFToken': CSRF_TOKEN}
});
})
Setting the token just for Backbone by overriding Backbone.sync:
var oldSync = Backbone.sync;
Backbone.sync = function(method, model, options){
options.beforeSend = function(xhr){
xhr.setRequestHeader('X-CSRFToken', CSRF_TOKEN);
};
return oldSync(method, model, options);
};
EDIT: Fixed a typo Kadam points at in comments
You can use a prefilter to add the token to all requests:
$.ajaxPrefilter(function(opts) {
if (opts.data) {
opts.data += "&";
}
opts.data += "csrfToken=" + token;
});
You may need to add additional logic if you don't always send the token.
Here's an updated version, based in Django 1.7 (using the jQuery cookie plugin)
oldSync = Backbone.sync
Backbone.sync = (method, model, options) ->
csrfSafeMethod = (method) ->
# these HTTP methods do not require CSRF protection
/^(GET|HEAD|OPTIONS|TRACE)$/.test method
options.beforeSend = (xhr, settings) ->
if !csrfSafeMethod(settings.type) and !@crossDomain
xhr.setRequestHeader 'X-CSRFToken', $.cookie('csrftoken')
return
oldSync method, model, options
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With