1

I have a strange issue with CSRF in Django. Here are the relevant portions:

In my javascript file I have:

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));
}

$(function () {
  $.ajaxSetup({
    beforeSend: function(xhr, settings) {
        if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
            xhr.setRequestHeader("X-CSRFToken", csrftoken);
        }
    }
  });
})

$.post('/api/jpush',
  $.param({'recipients': recipients, 'message': message, 'url': url,
           'url_title': url_title, 'priority': priority,
             'csrftoken': getCookie('csrftoken')}),
...

then I have in my view:

def push(request):    
  return render(request, 'api/push.html')    

def jpush(request):
  tmplData = {'result': False}

  if not request.POST:
    return HttpResponseBadRequest(request)
  elif request.POST.viewkeys() & {'recipients', 'message', 'priority'}:
    tmplData = { 'results': send(request.POST) }

  return JsonResponse(tmplData)

....

and in my template:

<form id="push" class="form-horizontal" action="" method="post">{% csrf_token %}

However when I post using ajax I get a 403 and firebug shows me that the crsftoken value is null and the csrftoken cookie is httpOnly. I have set CSRF_COOKIE_HTTPONLY to False in my settings.py so I don't understand why the cookie is being forced as httpOnly. I am using Django 1.10.

Thanks

echodrome
  • 141
  • 1
  • 11
  • Do you have an only http only cookie from before you set `CSRF_COOKIE_HTTPONLY = False`. Try clearing your cookies and trying again. – Alasdair Feb 09 '17 at 16:08
  • Yes, I have it set in my `settings.py` file and I have cleared cookies several times but according to firebug it always comes back as httponly. I tried viewing the cookies with `document.cookie` but it is not showing there either which confirms what firebug is showing. – echodrome Feb 09 '17 at 16:24
  • Make sure you've reset your server and then cleared the cookies after changing the settings. – Alasdair Feb 09 '17 at 16:26
  • I've tried that too, cleared browser cache and cookies, restarted the machine, the django server but to no avail. I've recreated my virtualenv as well, tried downgrading to Django 1.9 but nothing so far has worked – echodrome Feb 09 '17 at 16:33

1 Answers1

0

So I found a solution based on what kambiz mentioned here: Django CSRF check failing with an Ajax POST request

I modified the ajax parameter part to:

$.post('/api/jpush',
  $.param({'recipients': recipients, 'message': message, 'url': url,
           'url_title': url_title, 'priority': priority,
           'csrfmiddlewaretoken': $('input[name=csrfmiddlewaretoken]').val()}),
...

This still does not answer why Django is forcing the csfr cookie as httponly but at least I can continue working with the code

Community
  • 1
  • 1
echodrome
  • 141
  • 1
  • 11