1

I've set everything right as far as I can tell and it works in development:

I've included the following code:

function 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 = jQuery.trim(cookies[i]);
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) == (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}
var csrftoken = getCookie('csrftoken');

function csrfSafeMethod(method) {
    // these HTTP methods do not require CSRF protection
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
    beforeSend: function(xhr, settings) {
        if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
            xhr.setRequestHeader("X-CSRFToken", csrftoken);
        }
    }
});

what could be the reason the this would work on development but not in production?

davegri
  • 2,206
  • 2
  • 26
  • 45
  • Have you confirmed that this code is indeed included in production? Can you see it in the dev tools? I've many of times have forgotten to run `collectstatic` after deploying static files. – Austin Oct 07 '15 at 13:50
  • Yeah its included definitely. I just typed `getCookie('csrftoken')` into the console and it returned `null` whats up with that? – davegri Oct 07 '15 at 13:51
  • When you say it fails, what is the exact failure you're getting? Call doesn't trigger, error back from server, ect? – Austin Oct 07 '15 at 13:56
  • I'm getting the message you get when you don't send a csrftoken `CSRF verification failed. Request aborted.` I just typed in the console `document.cookie.indexOf('csrftoken')` and it returned `-1` so for some reason the cookie dosen't exist, what could cause this? – davegri Oct 07 '15 at 13:58
  • Double check whether the cookie is being sent, by using your browser's developer tools or `curl -i`. If, for example, [`CSRF_COOKIE_HTTPONLY = True`](https://docs.djangoproject.com/en/1.8/ref/settings/#csrf-cookie-httponly), then JavaScript will not be able to read the cookie and it will not appear in `document.cookie`. – Alasdair Oct 07 '15 at 14:53

2 Answers2

1

One possible reason could be that you have CSRF_COOKIE_SECURE = True in your production setttings. This will send the cookie only with HTTPS connections. If you have enabled this, and yet would like a view to handle a POST request without a CSRF token, decorate the view with csrf_exempt.

Edit: Also check if SESSION_COOKIE_SECURE is enabled. If set to True, you can encounter this problem.

I had a similar problem and addressed it by moving urls for signed in users (Django admin pages) to be served only through HTTPS thereby negating the need for the latter setting. I still keep CSRF_COOKIE_SECURE = True and the single URL that I needed to handle a POST request (set_language) wrapped with @csrf_exempt so that it can bypass this setting. This means that any views that need to handle forms for anonymous sessions need to be similarly decorated as well.

All seems to work well for now, but am still doing research to see if there are any other security implications to my configuration. Also, there could be a better way to handle this. Until then, I can live with this approach. HTH.

Hari Mahadevan
  • 920
  • 7
  • 14
  • Found another thread around my answer, http://stackoverflow.com/questions/25508605/how-to-get-some-user-identity-information-in-http-when-session-cookie-secure-t – Hari Mahadevan Oct 16 '15 at 02:58
0

In my case the following fixed the problem:

@ensure_csrf_cookie
def your_view(request)

According to docs, the csrf cookie may not be set if there's no form with {% csrf_token %} in it.

https://docs.djangoproject.com/en/1.10/ref/csrf/#django.views.decorators.csrf.ensure_csrf_cookie

Patrik Beck
  • 2,455
  • 1
  • 19
  • 24