I am having a bit of an issue with my current development setup when it comes to CSRF verification. Since I am running an angular development server and a django development server side by side and (naturally) need to send requests to the backend, CSRF becomes an issue. Django usually hands the token out when a user connects, but now that the front- and backend are so disconnected I do not get the CSRF token in the natural way.
What I now tried was to add a @csrf_exempt
decorated function to be able to get the cookie, also by decorating the function with @ensure_csrf_cookie
. The problem I am having is that still when setting the appropriate header for the request to include the CSRF token, the server still returns me a message saying that the CSRF cookie was not included (bullshit!).
So, my question is firstly how to properly set the header for the CSRF token, this is how I currently do it (typescript below):
constructor(private httpClient: HttpClient) {
const cookies = document.cookie.split(';');
for (let cookie of cookies) {
cookie = cookie.trim();
const re = new RegExp('^csrftoken');
if (re.test(cookie)) {
this.csrfToken = cookie;
// this.csrfToken = cookie.substr(10, cookie.length);
break;
}
}
console.log('[RequestService] Got token: ' + this.csrfToken);
}
post(url: string, body: {}) {
return this.httpClient.post(url, body, { headers: new HttpHeaders({ 'x-csrftoken': this.csrfToken }) });
}
As you can see above, I have commented out a part of the cookie extraction. The commented part will remove the initial 'csrftoken=' and leave the token itself. Should I trim away the 'csrftoken=' part or leave it there?
Here is the django view that I wanted to use to get an updated cookie:
@csrf_exempt
@ensure_csrf_cookie
def get_csrf_token(request):
return HttpResponse(status=200)
The request goes through to the function, but when I manually check the current cookies I have with document.cookies
I see that it is still the same old crappy cookie which has not updated :(.
I thought about using the CSRF_USE_SESSIONS setting in django to force each request to send an updated CSRF instead, but that seems like overkill for such a simple problem.
Please advise!
The answer lied in that I needed to set another option on my http request. The request has another option field called withCredentials
that needs to set to true in order to include CSRF information.
I also needed to substring the cookie I got to only include the CSRF token without the prepended "csrftoken=" which was done in the commented out line inside the constructor where I extracted it.