Django csrf token + Angularjs

Django and AngularJS both have CSRF support already, your part is quite simple.

First, you need to enable CSRF in Django, I believe you have already done so, if not, follow Django doc https://docs.djangoproject.com/en/1.5/ref/contrib/csrf/#ajax.

Now, Django will set a cookie named csrftoken on the first GET request and expects a custom HTTP header X-CSRFToken on later POST/PUT/DELETE requests.

For Angular, it expects the cookie named XSRF-TOKEN and will do POST/PUT/DELETE requests with X-XSRF-TOKEN header, so you need to do a little bit tweak to make the two go with each other:

$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';

Add above two lines somewhere in your js code, module.config() block is a good place for this.

That's it.

NOTE: This is for angular 1.1.5, older versions might need different approach.

Update:

Since the angular app isn't served by django, in order to let the cookie to be set, angular app needs to do a GET request to django first.


var foo = angular.module('foo', ['bar']);

foo.config(['$httpProvider', function($httpProvider) {
    $httpProvider.defaults.xsrfCookieName = 'csrftoken';
    $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
}]);

And all modules services and controllers, where $http used, will send requests with csrf token.


After searching around, what worked for me was from this post with the following code:

angular.module( '[your module name]',
    ... [some dependencies] ...
    'ngCookies',
    ... [other dependencies] ...
)
.run( function run( $http, $cookies ){

    // For CSRF token compatibility with Django
    $http.defaults.headers.post['X-CSRFToken'] = $cookies.get('csrftoken');
})

This is of course after getting the cookie through a GET request from the django server.

I also looked into some of the other answers here, including Ye Liun's but couldn't find anything in the official docs specifying changes to the defaults options for xsrf on $httpProvider, other than this pull request which didn't work for me at the time of me writing this post.


I created a Django App for my AngularJS app, in the same Django project as my (REST) API Django App, that only serves the index.html file (which is just a sym.link). In this way the CSRF Cookie is set without an additional GET request.

Please see my answer here about AngularJS Single Page Web Application on Sub-domain A talking to a Django JSON (REST) API on Sub-domain B using CORS and CSRF protection