django no csrftoken in cookie
Asked Answered
I

5

18

I'm testing to make a POST ajax request and I got a 403 because of no csrftoken. I followed the Document, however, it still doesn't work and I found that the cookie named csrftoken is empty, it means $.cookie("csrftoken") return null.

Can someone tell me the reason and how to set csrftoken into cookie?

Invagination answered 16/11, 2012 at 8:7 Comment(2)
Had a similar issue before, was to do with the csrf_protect decorator.If you are posting from a page to another url(ajax for Example) and If you are using @csrf_protect decorator etc make sure both the view you are posting the data from and the url recieving the post data to have this decorator.Cassock
your view, your template form?Isoleucine
G
23

I think you should provide the code how you get the csrf token in your HTML/JS code and settings for your middlewares.

First of all you should check that django.middleware.csrf.CsrfViewMiddleware is turned on.

I had a similar issue, when in python code I used request.META.get('CSRF_COOKIE') to get the token.

When you use this token in template - {% csrf_token %} Django notes that the token was rendered and sets the Cookie in CsrfViewMiddleware.process_response. If you get the token value in other way Django will miss this flag. So it will generate you a token but will not set the corresponding cookie.

I have 2 workarounds in code. You should add it to your views that are used to generate templates with JS code.

1. You can force Django to set the CSRF Cookie:

# Force updating CSRF cookie
request.META["CSRF_COOKIE_USED"] = True

2. Django sets the CSRF_COOKIE_USED automatically if you call get_token

from django.middleware.csrf import get_token
# don't use direct access to request.META.get('CSRF_COOKIE')
# in this case django will NOT send a CSRF cookie. Use get_token function
csrf_token = get_token(request)

Each one of this solutions should work separately. I advice to use get_token

Graecize answered 16/11, 2012 at 9:38 Comment(0)
D
16

You probably want to use the ensure_csrf_cookie view decorator (available since Django 1.4). This will set the csrftoken cookie even if you don't use the {{ csrf_token }} template tag.

Divulge answered 10/4, 2013 at 6:52 Comment(0)
E
6

I had the same problem ($.cookie('csrftoken') returned 'undefined').

The problem was in my Django configuration, I commented the following line and it works:

#CSRF_COOKIE_HTTPONLY = True  # Prevent client-side JavaScript access to the CSRF cookie
Excellency answered 7/10, 2014 at 14:57 Comment(2)
Yeah, The http-only cookie can't access by javascript in a browse.Invagination
@Excellency where do you comment it?Eleanor
M
3

First of all, if you are designing the application, it is always better to use csrf Token in a header or in POST request rather than in a cookie, because:

  • All forms must have the value added to its HTML dynamically. Any AJAX POSTs must also include the value.
  • The cookie will be submitted for every request (i.e. all GETs for images, CSS, JS, etc, that are not involved in the CSRF process) increasing request size.

If you want to force usage of cookies in django, you could always:

request.META["CSRF_COOKIE_USED"] = True

in your project if you are not using {% csrf_token %} anywhere. According to [documentation][1], you are not required to do anything else, but write a simple javascript code. Actually it's not true. You have to put "request.META['CSRF_COOKIE_USED'] = True" line in every view (or write appropriate decorator).

Mastitis answered 18/4, 2016 at 19:46 Comment(1)
did you consider making a pull request on documentation to include this?Alboin
U
2

Expanding on o_c's answer: by commenting the CSRF_COOKIE_HTTPONLY line, csrf_token value is no longer 'undefined' (in Firefox firebug) and is shown as the 'real' value, e.g. 'qGuPe2Q7... etc.'.

Ajax request is no longer rejected with 403 Forbidden error and is correctly executed (provided that csrf_token is set in the AJAX header).

        $.ajaxSetup({
            beforeSend: function(xhr, settings) {
                 if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                 xhr.setRequestHeader("X-CSRFToken", csrftoken);
                }
             }
        });
Utimer answered 18/4, 2016 at 19:26 Comment(1)
How to get the csrftoken in the frontend?Eleanor

© 2022 - 2024 — McMap. All rights reserved.