21

i am trying to do a login in django but i get this error, i check the CSRF documentation and nothing works for me.

Here is the HTML:

<body>
  <section class="container">
    <div class="login">
      <h1>Login to Web App</h1>

      {% if form.errors %}
        <p class="error">Lo sentimos, la combinacion de usuario y contrasena no es correcta!</p>
      {% endif %}  

      <form action="/accounts/auth/" method="post">
      {% csrf_token %}  
      <input type='hidden' name='csrfmiddlewaretoken' value='randomchars'/>

        <p><input name="username" type="text" name="login" value="" placeholder="Username"></p>

        <p><input name="password" type="password" name="password" value="" placeholder="Password"></p>

        <p class="submit"><input type="submit" name="commit" value="Login"></p>
      </form>
    </div>
</body>

Like you see above i use the {% csrf_token %} and i have 'django.middleware.csrf.CsrfViewMiddleware' in my installed apps.

And my views are:

from django.http import HttpResponse,HttpResponseRedirect
from django.template.loader import get_template 
from django.template import Context
from datetime import datetime
from django.shortcuts import render_to_response
from django.http import HttpResponseRedirect
from django.contrib import auth
from django.core.context_processors import csrf

from models import *
from django.shortcuts import get_object_or_404
from forms import *
from django.template.context import RequestContext
from django.contrib.auth.decorators import login_required
from django.contrib.auth import authenticate, login

def login(request):
    c = {}
    c.update(csrf(request))
    return render_to_response('login.html', c)    


def auth_view(request):
    username = request.POST['username']
    password = request.POST['password']
    user = authenticate(username=username, password=password)
    if user is not None:
        auth.login(request.user)
        return HttpResponse('/accounts/loggedin') 
    else:
        return HttpResponse('/accounts/invalid')

i redirect to an other HTML file where i dont use the {% csrf_token %}.

Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129
BismarthSantana
  • 211
  • 1
  • 2
  • 4
  • I was suffered this error, even though using {% csrf_token %}. But after changing **render_to_response** to just **render**, It was solved. – Haegyun Jung Jan 12 '16 at 15:37

3 Answers3

29

Theory


A couple of things are required to make the csrf protection work (check out the docs):

  1. Your browser has to accept cookies from your server
  2. Make sure you have 'django.middleware.csrf.CsrfViewMiddleware' included as middleware in your settings.py (alternatively use the decorator csrf_protect() on particular views you want to protect)
  3. Make sure you pass on the csrf token from django.core.context_processors.csrf to the context manager.

When you load your page, have a look in the page source using your favorite browser. Don't open the template html file, open the url which point to the view containing the form. Look at where you placed the {% csrf_token %}. If you see something like

<input type='hidden' name='csrfmiddlewaretoken' value="jdwjwjefjwdjqwølksqøwkop2j3ofje" />

you should be ok.

If you on the other hand see NOTPROVIDED, something has gone wrong while creating the csrf token. By looking in the source code (context_processors.py and csrf.py), we can find out what:

  • csrf(request) returns {'csrf_token': 'NOTPROVIDED'} if get_token(request) returns None.
  • get_token(request) returns request.META.get("CSRF_COOKIE", None).

I assume this means that it would return None if the cookie isn't successfully created.

Fix


For you, this means that you should first replace

<form action="/accounts/auth/" method="post" {% csrf_token %}>

with

<form action="/accounts/auth/" method="post">
{% csrf_token %}
(...)
</form>

We'd like the csrf field to be inside <form>...</form>, not inside <form>. As the code is at the moment, it will be converted to

<form action="/accounts/auth/" method="post" <input type='hidden' name='csrfmiddlewaretoken' value='randomchars' />>

and we would rather like

<form action="/accounts/auth/" method="post">
<input type='hidden' name='csrfmiddlewaretoken' value='randomchars' />

After that - have a look at the source code, and see if you can find the csrf field. If you can see it, everything should work in theory.

You can also check that the csrf cookie has been set in your browser, e.g. in Chrome, right-click the web page, and select Insepect Element. Select the Resources tab, and click on cookies. You should find a cookie name csrftoken there.

If you still have problems, double-check the middleware tuple in your settings.py and double-check that your browser accept cookier from your server as described above.

Community
  • 1
  • 1
Steinar Lima
  • 7,644
  • 2
  • 39
  • 40
  • I did it, but still get nothing, same error comes out. Use the @csrf_exempt in my views but nothing still happen – BismarthSantana Jan 03 '14 at 13:27
  • Ok, but the HTML posted is from the /accounts/login/ URL , so when i click in submit(login) button it redirect me to /accounts/auth/ URL, that call the auth_view method in my views. i dont have a HTML file for the /accounts/auth/ URL. Maybe thats the problem... What you think? – BismarthSantana Jan 04 '14 at 04:35
  • @BismarthSantana I want the html you get when you are on the page with the submit button, and click View -> Source in your favourite browser. – Steinar Lima Jan 04 '14 at 04:55
  • @BismarthSantana I made a substansial edit to my answer - please have a look. – Steinar Lima Jan 04 '14 at 06:11
  • Great help! Did everything you told me, Still have the error... I have updated my code with all i have done and you can see it above. Also my browser is permitting cookies. – BismarthSantana Jan 04 '14 at 22:42
  • @BismarthSantana You need to paste the html which is _produced_ by the template, not the template itself. This means that you should go to the url which points to the login-view and copy the source from that page. The template engine should transform the {% csrf_token %} into either `NOTPROVIDED` or a input field. – Steinar Lima Jan 07 '14 at 23:28
  • Does anyone reading this have any insights into why this error would occur seemingly randomly? Users sometimes get this error when trying to save a form, yet I can open a copy of the form in a new tab in the same browser on the same computer, copy and paste their data into the second tab and save that just fine. I have RequestContext in my view, have django.middleware.csrf.CsrfViewMiddleware in settings, and the form that generates the error has replaced {% csrf_token %} with inside
    .
    – jenniwren Dec 17 '14 at 19:16
  • I have no idea @jen - try asking a new question with as much context as possible. – Steinar Lima Dec 20 '14 at 02:30
  • Maybe this will help? https://stackoverflow.com/questions/44806375/django-csrf-failure-after-upgrade-1-9-1-11 – elnygren Sep 08 '17 at 10:46
3

Clear your browser cache and try again. Maybe it is using the CSRF token saved in cached cookie.

1

With Addition of above answer, Try Adding following lines in the views

from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def somathing():
   return something
Pradeep
  • 139
  • 1
  • 12