When I first paired up Django + React, I couldn’t figure out the whole CSRF token thing, so I avoided the whole issue by just using GET requests. Well that is no way to earn a living so I decided to figure it out today. Holy hell!
Everyone tells a nice little story about how this is supposed to work. You’ll see this getCookie method that looks something like this:
getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = $.trim(cookies[i]);
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
And then you’ll see some ajax configuration stuff like this:
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (settings.type=='POST') {
xhr.setRequestHeader("X-CSRFTOKEN", self.getCookie('csrftoken'));
}
}
});
And then boom it works, right? No, you also have to add some stuff to your settings.py that looks like this:
CORS_ALLOW_CREDENTIALS = True
CORS_ALLOW_HEADERS = list(default_headers) + [
'X-CSRFTOKEN',
]
CORS_ORIGIN_ALLOW_ALL = False
CORS_ORIGIN_WHITELIST = (
'http://localhost:3000',
)
CSRF_TRUSTED_ORIGINS = ['localhost:3000']
CSRF_COOKIE_SAMESITE = None
CSRF_COOKIE_SECURE = False
CSRF_COOKIE_HTTPONLY = False
And then some middleware like this:
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
... bla bla bla standard middleware ...
]
But it still doesn’t work! Oh wait you forgot the @ensure_csrf_cookie
decoration on your view, and did you try adding csrfmiddlewaretoken
to your POST data, or maybe you need to call django.middleware.csrf.get_token(request)
in your view… and if it still doesn’t work you can always forget the whole thing and use @csrf_exempt
which is looking pretty tempting right now because you’ve been scouring the internet for five hours trying to figure out what this thing’s problem is.
AND THEN finally you come across a stack overflow post with a little green checkmark and it’s the one…
xhrFields: {
withCredentials: true
}
Add that little sucker to your ajax request. And finally you can go to bed.