1

I have been getting sporadic CSRF errors in an app that is mostly working ok. I do everything as I'm supposed to do: I use {% csrf_token %} in my template for normal forms and in my ajax POSTs I set the X-CSRFToken header:

$.ajaxSetup({
    beforeSend: function(xhr, settings) {
        xhr.setRequestHeader("X-CSRFToken", $.cookie('csrftoken'));
    },
});

I'm even forcing the cookie to be set in all views by writing a custom Middleware that calls get_token

def CSRFForceCookieMiddleware(get_response):
    def middleware(request):
        response = get_response(request)
        get_token(request) # Force to set cookie in all responses
        return response
    return middleware

Everything works OK in my localhost and in production for most users. But for some users I get 403 CSRF validation error.

I added a lot of debug info. Turns out that even if CsrfViewMiddleware is setting the csrftoken is setting the cookie in the response, in the actual browser the cookie is not set ($.cookie('csrftoken') is null). So when the ajax call is made, there is no cookie present in the request.

So, I guess this pretty much means that some users' browsers are blocking this cookie? Anyone else had this experience?

Martin Massera
  • 1,718
  • 1
  • 21
  • 47
  • 3
    Most browsers have an option to "block all cookies". You may want to detect that in javascript and give your users a warning that some functional cookies are required for the site to work correctly. Alternatively, grab the token from a hidden input field (`{% csrf_token %}`) will add that field. – dirkgroten Aug 19 '19 at 10:18
  • @dirkgroten this is a good answer – Martin Massera Aug 19 '19 at 10:50

1 Answers1

3

Most browsers have an option to "block all cookies". You may want to detect that in javascript and give your users a warning that some functional cookies are required for the site to work correctly. There's another SO question that shows how to do that.

Alternatively, grab the token from a hidden input field ({% csrf_token %} will add that field in your template). That should always work.

dirkgroten
  • 20,112
  • 2
  • 29
  • 42
  • What I m not understanding is that the CSRF token seems to change many times, so if I have a page with many ajax POST requests, it may send the original token at page load which could have changed later – Martin Massera Aug 20 '19 at 07:21
  • 1
    the csrf middleware compares the token sent by the form with the token in the cookie/session. They both share a common secret but the one in the form is in addition salted with a changing salt. In the end all of the salted tokens are valid because they are based on the same secret. – dirkgroten Aug 20 '19 at 09:25