The Issue I'm Having
- I'm making an Ajax POST request from my Angular2 client to my Django (v1.9) backend (both on localhost, different ports). I'm not yet using the Django REST framework, I'm just dumping the JSON in Django without any add-ons.
- I have been issued a csrf token by the server, and I'm manually sending it back in the HTTP headers (I can see it there when I make the call).
- However, I still get the error from django: Forbidden (CSRF cookie not set.)
- I've read a number of other threads, and tried a few things, but still can't get Django to accept the CSRF token.
Client side code:
private _editUserUri = "http://127.0.0.1:8000/search/edit/user/";
constructor(private _http: Http){}
getCookie(name) {
let value = "; " + document.cookie;
let parts = value.split("; " + name + "=");
if (parts.length == 2)
return parts.pop().split(";").shift();
}
validateData(userdata) {
return true;
}
editUser(userdata) {
console.log("UserService: createUser function called");
console.log(JSON.stringify(userdata));
if(this.validateData(userdata)) {
let headers = new Headers({
'Content-Type': 'application/json',
'X-CSRFToken': this.getCookie('csrftoken')
});
let options = new RequestOptions({ headers: headers });
return this._http
.post(
this._editUserUri,
JSON.stringify(userdata),
options)
.map(res => {
console.log(res.json());
return res.json();
})
}
}
Screenshot of csrf token in header (x-csrftoken). This is exactly how Django expects it (source)
What I've tried / considered
I thought that perhaps the csrf token is out of date. I've tried to generate a new one, but I haven't yet managed to get Django to issue me a new one. I've tried using the @ensure_csrf_cookie decorator, but still nothing. If I have a csrf token in a cookie which was placed this morning, would I expect it to be replaced by a new, up-to-date version?
Another thought was that the header name (x-csrftoken) is in lower case. Django specifies that the header name should be the following: X-CSRFToken. However, from reading online it seems that headers should generally be case sensitive. In any case, Angular2 is automatically converting the header name to lower case.
I tried some other solutions I found on Stack Overflow (example) but had no luck.
I thought that maybe this was related to CORS, but the first OPTIONS request returns a 200 from my Django server. This pre-flight request wouldn't need to include the csrf token in its headers also, would it? (excuse my ignorance)
I'm pretty sure my settings are fine. I have 'django.middleware.csrf.CsrfViewMiddleware' in MIDDLEWARE_CLASSES, CSRF_COOKIE_SECURE = False, CORS_ALLOW_CREDENTIALS = True and CORS_ORIGIN_ALLOW_ALL = True
If anyone could help I'd greatly appreciate it!
Nick