Django CSRF problems with cookies disabled - django

While testing an application I've written in Django, I've found that I'm be thrown a HTTP 403 Forbidden error every time I submit a form. I am aware that the CSRF middleware checks for a cookie with the CSRF token - but what should my approach be given a user that has cookies disabled?
Do I need to be checking whether the user has cookies enabled in each of my views or is there a more efficient approach?
Thanks in advance.
This question dealt with Django pre-1.2 -- the solution is different if you have an older version.

Starting in Django 1.2 you can override the 403 response using CSRF_FAILURE_VIEW.

Just for anyone who has the same problem: I found that the best suited solution for me was writing some middleware that displays a generic 403 error page:
from django.http import HttpResponseForbidden
from django.conf import settings
from django.template import RequestContext
from django.shortcuts import render_to_response
class PermissionErrorMiddleware(object):
def process_response(self, request, response):
if isinstance(response, HttpResponseForbidden):
return render_to_response('403.html', context_instance=RequestContext(request))
return response
It instructs the user that the most likely cause for the error page is that cookies are disabled (among other things), because my application doesn't really throw 403 errors otherwise. I have always preferred the "security through obscurity" approach, and throw 404 errors when a user shouldn't be accessing a particular page.

If the form really must work without cookies, I think you just have to disable the CSRF middleware. You might be able to implement something similar using two form inputs where the value of one is random, and the other is a hash of the fist one and a secret.

Did you try to pass csrf information as a hidden POST variable? In projects that I have been involved in it is usually done with a hidden input:
<input type="hidden" name="csrf" value="<?=$person->csrf?>" />
Sorry for PHP code, I don't remember how to do it in Django Templates.

Related

Avoid csrf token in django post method

I am making part of the web app where (unlogged users, all visitors) can fill the form and I have to save that data (name, phone number, question) in database..
I am making REST using Django, but for frontend I will use React or Django, and I am making POST method in Django framework that reads JSON data from POST https request, and then I save that data to database.. But I get error CSRF verification failed. Request aborted. because I don not use CSRF token, because it is not required for this (I do not have logged users).
But I do not want to disable CSRF, because for admin page I would use this to authenticate users?
So anyone knows how to avoid using CSRF token for this method? Thanks in advance..
def saveDataToDatabase(request):
if request.method == 'POST':
json_data = json.loads(request.body)
try:
data = json_data['data']
except KeyError:
HttpResponseServerError("Malformed data!")
This is the part of method..
It's possible to disable csrf protection on a view with #csrf_exempt decorator.
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
def saveDataToDatabase(request):
# Your code here
More Infos on the Django doc
Have you thought about using Views to handle the requests? You may use these so you don´t have to do the next advice I´m giving you.
If the first advice wasn´t good enough, you may disable the csrf token in the settings file from Django. You need to remove (or comment) the django.middleware.csrf.CsrfViewMiddleware in the available Middleware list.
Any other question just ask. ;)

What is #csrf_exempt in Django?

What is #csrf_exempt, and why should we use this in our views.py? Also, are there any alternatives to it?
Normally when you make a request via a form you want the form being submitted to your view to originate from your website and not come from some other domain. To ensure that this happens, you can put a csrf token in your form for your view to recognize. If you add #csrf_exempt to the top of your view, then you are basically telling the view that it doesn't need the token. This is a security exemption that you should take seriously.
The decorator marks a view as being exempt from the protection ensured by the middleware. Example:
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
def my_view(request):
return HttpResponse('Hello world')
You should not have to use this unless you know exactly why. A good example where it is used is to build a webhook, that will receive informations from another site via a POST request. You then must be able to receive data even if it has no csrf token, but will be replaced by another system of security. For example, if you use stripe for the subscriptions of your clients, you need to know if a client unsubscribed his account. The webhook will be the way to inform your site, and then cut the access to your service for the unsubscribed client.

Using flatpages to create a simple facebook app, but CSRF problem caused by signed_request

I am trying to create a simple, html-only facebook app for a client's fb page. I would like to use django's flatpages so that the client and his staff can change the content of the app through the django admin of their site. The problem is that Django returns a 403 "CSRF verification failed. Request aborted." error when facebook attempts to send its own POST info and access the url of the app.
I already know about the #csrf_exempt decorator, but I am not sure how I would apply it to the flatpage view, as it is within the django.contrib code. Furthermore I would only want to disable csrf protection when the view is asked to call a specific facebook.html template (not not the default.html template). If there happened to be a {% crsf_exempt %} template tag for example, that would be perfect.
Can anyone think of a way to resolve this problem? Or maybe I should give up on the idea of using the django-flatpages to serve the facebook app?
Try using this decorator on your views that are called facebook:
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
this will disable csrf protection on that view.
Does this help?
I ran into the exact same problem as you. I wanted to diable csrf for flatpages (but not for the rest of the site) and ended up with the following middleware:
class DisableCSRFOnFlatPages(object):
def process_request(self, request):
try:
FlatPage.objects.get(url=request.META.get('PATH_INFO'))
setattr(request, '_dont_enforce_csrf_checks', True)
except FlatPage.DoesNotExist:
return
Add it to your settings and it should disable the csrf check whenever there's a flatpage.

SWFUpload with Django 1.2 csrf problem

I`m trying to upload files to Django with SWFUpload. Found this article Django with SWFUpload. But found one problem. In Django 1.2 a csrf requires a csrf token to be send on every form submit, and it includes files that are send with SWFUpload.So uploading doesnt until i turn off csrf ( globally or for view using #csrf_exempt decorator). Is there a better way to handle this rather than turning off csrf?
I know that i can pass custom data with SWFUpload post_params: {"csrfmiddlewaretoken" : ""},. But i don`t know how to get only value of csrf token in template, not a full input tag.
To retrieve the csrf token itself, you'll need to resort to using some of Django's internals. First off, include this line at the top of your view.
from django.middleware.csrf import get_token
Now, when passing parameters to your template, do something like
def my_view(request):
return render_to_response("index.html", {"csrf_token": get_token(request)})
In your template, just reference the token with {{ csrf_token }}.

Django CSRF framework cannot be disabled and is breaking my site

The django csrf middleware can't be disabled. I've commented it out from my Middleware of my project but my logins are failing due to missing CSRF issues. I'm working from the Django trunk. How can CSRF cause issues if it is not enabled in middleware?
I have to disable it because there are lots of POST requests on my site that CSRF just breaks. Any feedback on how I can completely disable CSRF in a django trunk project?
The "new' CSRF framework from Django's trunk is also breaking an external site that is coming in and doing a POST on a URL I'm giving them (this is part of a restful API.) I can't disable the CSRF framework as I said earlier, how can I fix this?
Yes, Django csrf framework can be disabled.
To manually exclude a view function from being handled by any CSRF middleware, you can use the csrf_exempt decorator, found in the django.views.decorators.csrf module. For example: (see doc)
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
def my_view:
return Httpresponse("hello world")
..and then remove {% csrf_token %} inside the forms from your template,or leave other things unchanged if you have not included it in your forms.
You can disable this in middleware.
In your settings.py add a line to MIDDLEWARE_CLASSES:
MIDDLEWARE_CLASSES = (
myapp.disable.DisableCSRF,
)
Create a disable.py in myapp with the following
class DisableCSRF(object):
def process_request(self, request):
setattr(request, '_dont_enforce_csrf_checks', True)
Basically if you set the _dont_enforce_csrf_checks in your request, you should be ok.
See answers below this for a better solution. Since I wrote this, a lot has changed. There are now better ways to disable CSRF.
I feel your pain. It's not acceptable for a framework to change such fundamental functionality. Even if I want to start using this from now on, I have legacy sites on the same machine sharing a copy of django. Changes like this should require major version number revisions. 1.x --> 2.x.
Anyway, to fix it I just commented it out and have stopped updating Django as often.
File: django/middleware/csrf.py
Around line 160:
# check incoming token
# request_csrf_token = request.POST.get('csrfmiddlewaretoken', None)
# if request_csrf_token != csrf_token:
# if cookie_is_new:
# # probably a problem setting the CSRF cookie
# return reject("CSRF cookie not set.")
# else:
# return reject("CSRF token missing or incorrect.")
In general, you shouldn't be disabling CSRF protection, since doing so opens up security holes. If you insist, though…
A new way of doing CSRF protection landed in trunk just recently. Is your site by chance still configured to do it the old way? Here are the docs for The New Way™ and here are the docs for The Old Way™.
I simply tried removing the references to csrf middleware classes from my settings.py, it worked. Not sure if this is acceptable. Any comments?
Below two lines were removed -
'django.middleware.csrf.CsrfViewMiddleware',
'django.middleware.csrf.CsrfResponseMiddleware',
my django version is 1.11. the middleware should be like this:
from django.utils.deprecation import MiddlewareMixin
class DisableCSRF(MiddlewareMixin):
def process_request(self, request):
setattr(request, '_dont_enforce_csrf_checks', True)