125

I have some problem for a while now, I'm experiencing CSRF Cookie not set. Please look at the code below:

views.py:

def deposit(request, account_num):
    if request.method == 'POST':
        account = get_object_or_404(account_info, acct_number=account_num)
        form_ = AccountForm(request.POST or None, instance=account)
        form = BalanceForm(request.POST)
        info = str(account_info.objects.filter(acct_number=account_num))
        inf = info.split()
        
        if form.is_valid():

            # cd=form.cleaned_data
            now = datetime.datetime.now()
            cmodel = form.save()
            cmodel.acct_number = account_num
            
            # RepresentsInt(cmodel.acct_number)
            cmodel.bal_change = "%0.2f" % float(cmodel.bal_change)
            cmodel.total_balance = "%0.2f" % (float(inf[1]) + float(cmodel.bal_change))
            account.balance = "%0.2f" % float(cmodel.total_balance)
            cmodel.total_balance = "%0.2f" % float(cmodel.total_balance)
            
            # cmodel.bal_change=cmodel.bal_change
            cmodel.issued = now.strftime("%m/%d/%y %I:%M:%S %p")
            account.recent_change = cmodel.issued
            cmodel.save()
            account.save()
            
            return HttpResponseRedirect("/history/" + account_num + "/")
        
        else:
            return render_to_response('history.html',
                                      {'account_form': form},
                                      context_instance=RequestContext(request))

Template file:

<form action="/deposit/{{ account_num }}/" method="post">
    <table>
        <tr>
            {{ account_form.bal_change }}
            &nbsp;
            <input type="submit" value="Deposit"/>
        </tr>
        {% csrf_token %}
    </table>
</form>

I'n stuck, I already cleared the cookie, used other browser but still csrf cookie not set.

starball
  • 20,030
  • 7
  • 43
  • 238
  • 2
    Do you have `CsrfViewMiddleware` in your `MIDDLEWARE_CLASSES` setting? – alecxe Jul 18 '13 at 07:04
  • Add `{%csrf_token%}` in your form in the template. – Rohan Jul 18 '13 at 07:05
  • 4
    @Rohan it's already there, see the question. – alecxe Jul 18 '13 at 07:07
  • 1
    Yup, I already have CsrfViewMiddleware, and I already have the csrf_token in my form –  Jul 18 '13 at 07:47
  • I've been using the Django cors module and accessing it through ReactJS. (Both were on localhost). I also had this problem of the OP. I found for me that adding `credentials: 'include'` to the POST request and then ALSO adding in django's settings.py: `CORS_ALLOW_CREDENTIALS = True` seems to have fixed the problem without the need for adding `@csrf_exempt` to the view. It is actually in the docs... https://pypi.org/project/django-cors-headers-multi/ *I know this relates to one of the questions above but I can't comment yet and wanted to hopefully save someone else the time it took me to find t – D W Jun 10 '18 at 04:07
  • Well in my case some cookies were blocked so just try allowing them a lets see what happens – Uthman Tanko Apr 03 '21 at 10:51

26 Answers26

170

This can also occur if CSRF_COOKIE_SECURE = True is set and you are accessing the site non-securely or if CSRF_COOKIE_HTTPONLY = True is set as stated here and here

Druska
  • 4,752
  • 2
  • 30
  • 34
89
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt

@csrf_exempt 
def your_view(request):
    if request.method == "POST":
        # do something
    return HttpResponse("Your response")
akaRem
  • 7,326
  • 4
  • 29
  • 43
  • 119
    Disabling the security mechanism entirely is not a good way to fix the error. – Guillaume Algis Oct 27 '16 at 13:10
  • 2
    If you are using cookiecutter-django in 2017 this is the correct answer in production. – André Duarte Jan 16 '17 at 23:09
  • 1
    Why is that, out of curiosity? – Patrick Gallagher May 27 '18 at 07:33
  • 14
    This answer does not suggest to "disable the security mechanism entirely", it only tells how to do that for a single case where you might not be able to use the CSRF token. This is my case, where I need to offer a POST action to an external client. – mariotomo Sep 22 '19 at 17:48
  • This is a TODO kind of item that i use during the development phase, when you can't provide csrf token from UI. But certainly not recommended for a live app. – Aman Madan Sep 06 '20 at 17:43
  • One can add a whitelist of trusted origins by adding CSRF_TRUSTED_ORIGINS in the settings.py file. Add a list of trusted domains and use csrf_exempt decorator for the view. This is what worked for me in allowing webhooks in my application. Try CSRF_TRUSTED_ORIGINS = ['*'] to see if it works – Amal Vijayan Feb 13 '21 at 15:21
  • Disabling the csrf check is not a option here – Premkumar chalmeti Sep 08 '22 at 10:21
29

If you're using the HTML5 Fetch API to make POST requests as a logged in user and getting Forbidden (CSRF cookie not set.), it could be because by default fetch does not include session cookies, resulting in Django thinking you're a different user than the one who loaded the page.

You can include the session token by passing the option credentials: 'include' to fetch:

var csrftoken = getCookie('csrftoken');
var headers = new Headers();
headers.append('X-CSRFToken', csrftoken);
fetch('/api/upload', {
    method: 'POST',
    body: payload,
    headers: headers,
    credentials: 'include'
})
user85461
  • 6,510
  • 2
  • 34
  • 40
  • may i know what is that Header() method you instantiated? is that global javascript method? – Abz Rockers Feb 03 '18 at 06:38
  • @AbzRockers: Yes, `Headers` is a global javascript interface, part of the HTML5 Fetch API. https://developer.mozilla.org/en-US/docs/Web/API/Headers – user85461 Feb 28 '18 at 17:15
  • getting getCookie is not defined – nassim May 24 '21 at 13:33
  • `getCookie` is not a global/built-in. Here's Django's example implementation of a function to get cookie values by name: https://docs.djangoproject.com/en/3.2/ref/csrf/#ajax There are loads of other options; hear are some: https://stackoverflow.com/questions/14573223/set-cookie-and-get-cookie-with-javascript/24103596#24103596 – user85461 May 24 '21 at 16:33
  • 1
    It always surprises me that you have to include both the cookie and the header. One would think that one is enough since they have the same value. Does anyone know why both are required? – Benoit Blanchon May 17 '22 at 11:19
  • 1
    @lionelbrits With Django, the default is `X-CSRFToken`. https://docs.djangoproject.com/en/4.0/ref/csrf/#ajax You might be using a different framework, or if you are using Django, you might have customized some things with the `CSRF_HEADER_NAME` setting. – user85461 Jun 07 '22 at 13:41
  • @user85461 you are correct. Must be brain fog. – lionelbrits Jun 08 '22 at 21:01
25

From This You can solve it by adding the ensure_csrf_cookie decorator to your view

from django.views.decorators.csrf import ensure_csrf_cookie
@ensure_csrf_cookie
def yourView(request):
 #...

if this method doesn't work. you will try to comment csrf in middleware. and test again.

Community
  • 1
  • 1
dscanon
  • 275
  • 3
  • 6
10

If you're using DRF, check if your urlpatterns are correct, maybe you forgot .as_view():

So that how mine code looked like:

urlpatterns += path('resource', ResourceView) 

And that's how it should like:

urlpatterns += path('resource', ResourceView.as_view())
Alveona
  • 850
  • 8
  • 17
6

I came across a similar situation while working with DRF, the solution was appending .as_view() method to the view in urls.py.

Paolo
  • 20,112
  • 21
  • 72
  • 113
Pratik Mhatre
  • 779
  • 7
  • 12
  • It would be better if you included some code as well – Ghasem Apr 17 '19 at 07:29
  • 2
    @AlexJolig just faced the same issue, the problem was that I forgot to add `.as_view()` aftrer my ApiView So that how code looked like: `urlpatterns += path('resource', ResourceView)` And that's how it should like: `urlpatterns += path('resource', ResourceView.as_view())` – Alveona Feb 20 '20 at 14:38
3

try to check if your have installed in the settings.py

 MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',)

In the template the data are formatted with the csrf_token:

<form>{% csrf_token %}
</form>
drabo2005
  • 1,076
  • 1
  • 10
  • 16
  • i don't have all your code but i believe that the matter is here : def deposit(request,account_num): changed it to def deposit(request): and find a way to callback the account_num. now it going to depend if the account_num is a table field or a variable. – drabo2005 Jul 18 '13 at 07:52
  • It is a variable {{ account_num }}, but how does this affect the csrf token? –  Jul 18 '13 at 08:04
  • i believe that the csrf token refered only to the request , so it cannot verify or handle what going with the variable here. check the djangoproject.com may be you could get a proper answer about the csrf_token. – drabo2005 Jul 18 '13 at 08:12
1

This problem arose again recently due to a bug in Python itself.

http://bugs.python.org/issue22931

https://code.djangoproject.com/ticket/24280

Among the versions affected were 2.7.8 and 2.7.9. The cookie was not read correctly if one of the values contained a [ character.

Updating Python (2.7.10) fixes the problem.

sbaechler
  • 1,329
  • 14
  • 21
1

This also occurs when you don't set the form action.
For me, it was showing this error when the code was:

<form class="navbar-form form-inline my-2 my-lg-0" role="search" method="post">

When I corrected my code into this:

<form class="navbar-form form-inline my-2 my-lg-0" action="{% url 'someurl' %}" role="search" method="post">

my error disappeared.

סטנלי גרונן
  • 2,917
  • 23
  • 46
  • 68
1

If you are not using {% csrf_token %} tag in the template you are rendering. Django won't set the csrftoken cookie.

To force django to set the csrftoken cookie, add ensure_csrf_cookie decorator in you view.

from django.views.decorators.csrf import ensure_csrf_cookie

@ensure_csrf_cookie
def myview(request):
Al Mahdi
  • 635
  • 1
  • 9
  • 16
1

In my particular case, the problem is that I was using the Django rest_framework and forgot to add the following decorators to my function:

from rest_framework.decorators import api_view, renderer_classes

@api_view(('POST',))
@renderer_classes((JSONRenderer,))
def handle_web_request(request):
    ...
xjcl
  • 12,848
  • 6
  • 67
  • 89
1

I get this error and change this:

<form method="post">

to this:

<form method="POST">

and it's solved ! Just upper case post make the problem ! I have not any issue with this on 127.0.0.1, but when i use 192.168.x.x address this broke my forms.

alireza
  • 1,173
  • 4
  • 19
  • 40
1

In my case, setting CSRF_COOKIE_SECURE to False wasn't enough but setting it to Null/ not specifying the parameter worked.

Puni188
  • 11
  • 3
1

In my case, the problem was that the path to the static files in nginx was incorrectly specified.

sudo tail -F /var/log/nginx/error.log

Check if there are errors in file paths.

Paolo
  • 20,112
  • 21
  • 72
  • 113
JopaBoga
  • 157
  • 11
0

Problem seems that you are not handling GET requests appropriately or directly posting the data without first getting the form.

When you first access the page, client will send GET request, in that case you should send html with appropriate form.

Later, user fills up the form and sends POST request with form data.

Your view should be:

def deposit(request,account_num):
   if request.method == 'POST':
      form_=AccountForm(request.POST or None, instance=account)
      if form.is_valid(): 
          #handle form data
          return HttpResponseRedirect("/history/" + account_num + "/")
      else:
         #handle when form not valid
    else:
       #handle when request is GET (or not POST)
       form_=AccountForm(instance=account)

    return render_to_response('history.html',
                          {'account_form': form},
                          context_instance=RequestContext(request))
Rohan
  • 52,392
  • 12
  • 90
  • 87
0

Check that chrome's cookies are set with default option for websites. Allow local data to be set (recommended).

CosmoRied
  • 876
  • 2
  • 10
  • 8
0

Method 1:

from django.shortcuts import render_to_response
return render_to_response(
    'history.html',
    RequestContext(request, {
        'account_form': form,
    })

Method 2:

from django.shortcuts import render
return render(request, 'history.html', {
    'account_form': form,
})

Because render_to_response method may case some problem of response cookies.

Paolo
  • 20,112
  • 21
  • 72
  • 113
0

I have just met once, the solution is to empty the cookies. And may be changed while debugging SECRET_KEY related.

Paolo
  • 20,112
  • 21
  • 72
  • 113
JunLe Meng
  • 33
  • 1
  • 4
0

Clearing my browser's cache fixed this issue for me. I had been switching between local development environments to do the django-blog-zinnia tutorial after working on another project when it happened. At first, I thought changing the order of INSTALLED_APPS to match the tutorial had caused it, but I set these back and was unable to correct it until clearing the cache.

Paolo
  • 20,112
  • 21
  • 72
  • 113
datasmith
  • 704
  • 8
  • 14
0

I was using Django 1.10 before.So I was facing this problem. Now I downgraded it to Django 1.9 and it is working fine.

0

Make sure your django session backend is configured properly in settings.py. Then try this,

class CustomMiddleware(object):
  def process_request(self,request:HttpRequest):
      get_token(request)

Add this middleware in settings.py under MIDDLEWARE_CLASSES or MIDDLEWARE depending on the django version

get_token - Returns the CSRF token required for a POST form. The token is an alphanumeric value. A new token is created if one is not already set.

Ghasem
  • 14,455
  • 21
  • 138
  • 171
arp
  • 1,358
  • 10
  • 13
0

I had the same error, in my case adding method_decorator helps:

from django.views.decorators.csrf import csrf_protect
from django.utils.decorators import method_decorator

method_decorator(csrf_protect)
def post(self, request):
    ...
moszoro
  • 13
  • 4
0

Just want to point out my case here as someone might cross the same fields.

Forbidden (CSRF cookie not set.): /main/staff/products/validation/create
HTTP POST /main/staff/products/validation/create 403 [0.01, 127.0.0.1:55940]

This thing was driving me insane... So, by commenting CSRF middleware

 MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
 # 'django.middleware.csrf.CsrfViewMiddleware',
)

it gave me

POST Method not allowed.

That was my hint, after all. I was sure Post method was present. Turns out my url_patterns was leading to another view by a regex bug.

So no matter what I was doing in my view, @csrf_exempt @ensure_crsf_cookie, looking for .as_view()... I was looking at the wrong view.

So, if nothing works, make sure your are actually being sent to the right view.

0

You can get this error while deploing Django application with NO SSL. If this is the case then putting an SSL reverse-proxy or SSL-configured Ingress in front of backend will solve the problem.

0

I just tried this solution it work for me. You have to set CSRF_USE_SESSIONS to True, basically the csrf token will be stored in a session https://docs.djangoproject.com/en/4.1/ref/settings/#std-setting-CSRF_USE_SESSIONS

-4

In your view are you using the csrf decorator??

from django.views.decorators.csrf import csrf_protect

@csrf_protect def view(request, params): ....

Noopur Phalak
  • 878
  • 1
  • 13
  • 22
abhishekgarg
  • 1,480
  • 9
  • 14