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