Avoid csrf token in django post method - django

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

Related

csrf_exempt set but CSRF Failed: Referer checking failed - no Referer

I have a backend API, it's in django and deployed on Google Endpoint.
I have a post request that insert data to my DB.
I created a script to use this endpoint but I got this error:
{"detail":"CSRF Failed: Referer checking failed - no Referer."}
Regarding over posts I added the crsf_exempt decorator to my class but it did not change.
I try to add the decorator two ways:
class AddUser(APIView):
""" Create user and company from csv """
#method_decorator(csrf_exempt)
def post(self, request):
#method_decorator(csrf_exempt, name='dispatch')
class AddUser(APIView):
""" Create user and company from csv """
def post(self, request):
But both failed.
This is how I contact my endpoint:
resp = requests.request(
method, url,
headers={'Authorization': 'Bearer {}'.format(
open_id_connect_token)}, **kwargs)
Any ideas ?
Thanks
EDIT
So I tried to add authentication classes to my views but it appears to be a bad idea. This is being real trouble for me.
I tried to get the csrftoken doing like this:
client = requests.session()
# Retrieve the CSRF token first
client.get(url) # sets cookie
print(client.cookies)
if 'csrftoken' in client.cookies:
# Django 1.6 and up
csrftoken = client.cookies['csrftoken']
else:
# older versions
csrftoken = client.cookies
Thing is, I am using IAP to protect my API and I do not have any csrftoken cookie but I do have a something looking like this:
<RequestsCookieJar[<Cookie GCP_IAP_XSRF_NONCE_Q0sNuY-M83380ypJogZscg=1
for ...
How can I use this to make post request to my API ?
So this happened to me because I did not set any authentication_classes to my generic view.
When this option is not set Django automatically use the SessionBackend, which need the csrf token.
I fixed it by adding this to my view: authentication_classes = [ModelBackend, GoogleOAuth2]
#Kimor - Can you try doing this in your urls.py
from django.views.decorators.csrf import csrf_exempt
url('^test/$', csrf_exempt(views.TestView.as_view())),
The get and post methods defined on the APIView class just tell DRF how the actual view should behave, but the view method that the Django router expects is not actually instantiated until you call TestView.as_view().
source
Django REST Framework CSRF Failed: CSRF cookie not set
So after working on this project for a while this is what I learned regarding the CSRF using Django.
First of all, if you are using django templates, or in any cases where your back-end and front-end are running behind the same server the most common practice is to use session for authentication.
This is activated by default by DRF.
This means that in your DRF configuration if you do not explicitly set the DEFAULT_AUTHENTICATION_CLASSES option default authentication will be set to Session + BasicAuth.
In this configuration you'll need to manage the CSRF token as described in the documentation (https://docs.djangoproject.com/en/4.0/ref/csrf/).
If your back-end and front-end are separated as in my case, using CSRF is not the only solution or even the recommended one.
As in my case I use JWT behind IAP (Identity Aware Proxy, provided by google). I had to write my own authentication classes and then use it in my DRF conf:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'main.authentication_backend.custom_auth.IAPAuthentication'],
...
}
Here is explain how to write your own authentication class: https://www.django-rest-framework.org/api-guide/authentication/#custom-authentication.

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.

HTTP post request in Django

I am trying to do the following:
1) A payment solution is supposed to send an HTTP Post to my site
2) I would like to read the contents of the request(xml) and update my records to reflect the payment
I am trying this for the first time. When I create a URL path, and send a post to that address I get the csrf error.
Is there a way using Django wherein I can accept a post and don't have to return a response.
Thanks
Tanmay
Your view should return an http response, otherwise you will get an error. However, Django does not mind if that response does not contain any content. Your view can be as simple as:
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
def my_view(request):
# do something with request.POST
return HttpResponse("")
Since it is a third party that is submitting the post request, and not a user submitting a form on your site, you can mark the view as exempt from CSRF protection using the csrf_exempt decorator, as above.
Note that anyone could submit a post request to your url, so you should have some way of checking that the response is genuine. Your payment solution should be able to advise a suitable way to do this.

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.

Django CSRF problems with cookies disabled

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.