290π
Note: Disabling CSRF is unsafe from security point of view. Please use your judgement to use the below method.
Why this error is happening?
This is happening because of the default SessionAuthentication
scheme used by DRF. DRFβs SessionAuthentication
uses Djangoβs session framework for authentication which requires CSRF to be checked.
When you donβt define any authentication_classes
in your view/viewset, DRF uses this authentication classes as the default.
'DEFAULT_AUTHENTICATION_CLASSES'= (
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication'
),
Since DRF needs to support both session and non-session based authentication to the same views, it enforces CSRF check for only authenticated users. This means that only authenticated requests require CSRF tokens and anonymous requests may be sent without CSRF tokens.
If youβre using an AJAX style API with SessionAuthentication, youβll need to include a valid CSRF token for any "unsafe" HTTP method calls, such as PUT, PATCH, POST or DELETE
requests.
What to do then?
Now to disable csrf check, you can create a custom authentication class CsrfExemptSessionAuthentication
which extends from the default SessionAuthentication
class. In this authentication class, we will override the enforce_csrf()
check which was happening inside the actual SessionAuthentication
.
from rest_framework.authentication import SessionAuthentication, BasicAuthentication
class CsrfExemptSessionAuthentication(SessionAuthentication):
def enforce_csrf(self, request):
return # To not perform the csrf check previously happening
In your view, then you can define the authentication_classes
to be:
authentication_classes = (CsrfExemptSessionAuthentication, BasicAuthentication)
This should handle the csrf error.
44π
Easier solution:
In views.py, use django-bracesβ CsrfExemptMixin
and authentication_classes
:
# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from django.views.decorators.csrf import csrf_exempt
from braces.views import CsrfExemptMixin
class Object(CsrfExemptMixin, APIView):
authentication_classes = []
def post(self, request, format=None):
return Response({'received data': request.data})
- [Django]-How do I include related model fields using Django Rest Framework?
- [Django]-Django South β table already exists
- [Django]-Authenticate by IP address in Django
21π
Modify urls.py
If you manage your routes in urls.py, you can wrap your desired routes with csrf_exempt() to exclude them from the CSRF verification middleware.
import views
from django.conf.urls import patterns, url
from django.views.decorators.csrf import csrf_exempt
urlpatterns = patterns('',
url(r'^object/$', csrf_exempt(views.ObjectView.as_view())),
...
)
Alternatively, as a Decorator
Some may find the use of the @csrf_exempt decorator more suitable for their needs
for instance,
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse
@csrf_exempt
def my_view(request):
return HttpResponse('Hello world')
should get the Job Done!
- [Django]-In django, how do I sort a model on a field and then get the last item?
- [Django]-Altering one query parameter in a url (Django)
- [Django]-RuntimeWarning: DateTimeField received a naive datetime
18π
For all who did not find a helpful answer. Yes DRF automatically removes CSRF protection if you do not use SessionAuthentication
AUTHENTICATION CLASS, for example, many developers use only JWT:
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
),
But issue CSRF not set
may be occurred from some another reason, for exmple you not correctly added path to you view:
url(r'^api/signup/', CreateUserView), # <= error! DRF cant remove CSRF because it is not as_view that does it!
instead of
url(r'^api/signup/', CreateUserView.as_view()),
- [Django]-Django middleware difference between process_request and process_view
- [Django]-Django override save for model only in some cases?
- [Django]-Django self-referential foreign key
13π
I tried a few of the answers above and felt creating a separate class was a little overboard.
For reference, I ran into this problem when trying to update a function based view method to a class based view method for user registration.
When using class-based-views (CBVs) and Django Rest Framework (DRF), Inherit from the ApiView class and set permission_classes and authentication_classes to an empty tuple. Find an example below.
class UserRegistrationView(APIView):
permission_classes = ()
authentication_classes = ()
def post(self, request, *args, **kwargs):
# rest of your code here
- [Django]-Laravel's dd() equivalent in django
- [Django]-Serving Media files during deployment in django 1.8
- [Django]-Django filter JSONField list of dicts
7π
If you do not want to use session based authentication, you can remove Session Authentication
from REST_AUTHENTICATION_CLASSES and that would automatically remove all csrf based issues. But in that case Browseable apis might not work.
Besides this error should not come even with session authentication. You should use custom authentication like TokenAuthentication for your apis and make sure to send Accept:application/json
and Content-Type:application/json
(provided you are using json) in your requests along with authentication token.
- [Django]-How to manually assign imagefield in Django
- [Django]-How to force application version on AWS Elastic Beanstalk
- [Django]-Django.db.utils.ProgrammingError: relation "bot_trade" does not exist
5π
You need to add this to prevent default session authentication: (settings.py)
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
)
}
Then: (views.py)
from rest_framework.permissions import AllowAny
class Abc(APIView):
permission_classes = (AllowAny,)
def ...():
- [Django]-How to combine multiple QuerySets in Django?
- [Django]-Error: could not determine PostgreSQL version from '10.3' β Django on Heroku
- [Django]-Add a custom button to a Django application's admin page
5π
You need to be absolutely sure, that you want to switch off CSRF protection.
- Create file
authentication.py
and place it wherever you want in your project. For example, in foldersession_utils
. - Place this code in the file:
from rest_framework.authentication import SessionAuthentication
class SessionCsrfExemptAuthentication(SessionAuthentication):
def enforce_csrf(self, request):
pass
- When you want to make
POST
,PUT
,PATCH
orDELETE
requests to your view be sure that youβve changedSessionAuthentication
toSessionCsrfExemptAuthentication
from the new file. View example:
@api_view(["POST"])
@authentication_classes([SessionCsrfExemptAuthentication])
@permission_classes([IsAuthenticated])
def some_view(request) -> "Response":
# some logic here
return Response({})
This trick allow you to override method (pass) enforce_csrf
and the new session authentication class will skip CSRF check.
βοΈ
- [Django]-Is there a list of Pytz Timezones?
- [Django]-Remove pk field from django serialized objects
- [Django]-Getting Django admin url for an object
2π
I am struck with the same problem. I followed this reference and it worked.
Solution is to create a middleware
Add disable.py file in one of your apps (in my case it is βmyappβ)
class DisableCSRF(object):
def process_request(self, request):
setattr(request, '_dont_enforce_csrf_checks', True)
And add the middileware to the MIDDLEWARE_CLASSES
MIDDLEWARE_CLASSES = (
myapp.disable.DisableCSRF,
)
- [Django]-How do I run tests against a Django data migration?
- [Django]-Python Django Gmail SMTP setup
- [Django]-Django South β table already exists
2π
My Solution is shown blow. Just decorate my class.
from django.views.decorators.csrf import csrf_exempt
@method_decorator(csrf_exempt, name='dispatch')
@method_decorator(basic_auth_required(
target_test=lambda request: not request.user.is_authenticated
), name='dispatch')
class GenPedigreeView(View):
pass
- [Django]-Django-rest-framework returning 403 response on POST, PUT, DELETE despite AllowAny permissions
- [Django]-With DEBUG=False, how can I log django exceptions to a log file
- [Django]-How to automate createsuperuser on django?
1π
If you are using an exclusive virtual environment for your application, you can use the following approach without effective any other applications.
What you observed happens because rest_framework/authentication.py
has this code in the authenticate
method of SessionAuthentication
class:
self.enforce_csrf(request)
You can modify the Request
class to have a property called csrf_exempt
and initialize it inside your respective View class to True
if you do not want CSRF checks. For example:
Next, modify the above code as follows:
if not request.csrf_exempt:
self.enforce_csrf(request)
There are some related changes youβd have to do it in the Request
class
- [Django]-Find object in list that has attribute equal to some value (that meets any condition)
- [Django]-How can I upgrade specific packages using pip and a requirements file?
- [Django]-Django FileField upload is not working for me
1π
When using REST API POSTs, absence of X-CSRFToken request header may cause that error.
Django docs provide a sample code on getting and setting the CSRF token value from JS.
As pointed in answers above, CSRF check happens when the SessionAuthentication is used. Another approach is to use TokenAuthentication, but keep in mind that it should be placed first in the list of DEFAULT_AUTHENTICATION_CLASSES of REST_FRAMEWORK setting.
- [Django]-How to resize the new uploaded images using PIL before saving?
- [Django]-Running Django with FastCGI or with mod_python
- [Django]-Http POST drops port in URL
0π
This could also be a problem during a DNS Rebinding attack.
In between DNS changes, this can also be a factor. Waiting till DNS is fully flushed will resolve this if it was working before DNS problems/changes.
- [Django]-Django-celery: No result backend configured
- [Django]-Google Static Maps URL length limit
- [Django]-How to check Django version
0π
For me, using django 3.1.5
and django rest framework 3.12
the solution was way easier.
It happened to me that on a views.py
file I had defined this two methods:
@api_view(['POST'])
@permission_classes((IsAuthenticated, ))
def create_transaction(request):
return Response(status=status.HTTP_200_OK)
def create_transaction(initial_data):
pass
On my urls.py
:
urlpatterns = [
path('transaction', views.create_transaction, name='transaction'),
]
Django was picking the latest and throwing the error. Renaming one of the two solved the issue.
- [Django]-Django gunicorn sock file not created by wsgi
- [Django]-Delete multiple objects in django
- [Django]-Negating a boolean in Django template
0π
Code bellow would remove demand for CSRF. Even anon user would be able to send request.
from typing import List, Any
class Object(APIView):
authentication_classes: List = []
permission_classes: List[Any] = [AllowAny]
...
...
- [Django]-How can I activate the unaccent extension on an already existing model
- [Django]-How do I install psycopg2 for Python 3.x?
- [Django]-Django manage.py runserver invalid syntax
0π
class MyViewSet(ViewSet):
def initialize_request(self, request, *args, **kwargs):
""" remove csrf protection """
res = super(VolumeManagerViewSet, self).initialize_request(request, *args, **kwargs)
setattr(request, '_dont_enforce_csrf_checks', True)
return res
You can override initialize_request
method to remove csrf protection.
- [Django]-405 "Method POST is not allowed" in Django REST framework
- [Django]-How to get the name of current app within a template?
- [Django]-Dynamically adding a form to a Django formset
-1π
Removing CSRF check is not always the only (or best) solution. Actually, itβs an important security mechanism for SessionAuthentication
.
I was having the same issue when trying to authenticate with JWT and doing a POST request.
My initial setup looked like this:
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": (
"rest_framework.authentication.SessionAuthentication",
"django_cognito_jwt.JSONWebTokenAuthentication",
),
...
}
As SessionAuthentication
was checked first in the list, the CSRF error was raised. My solution was as simple as changing the order to always check JWT auth first. Like this:
"DEFAULT_AUTHENTICATION_CLASSES": (
"django_cognito_jwt.JSONWebTokenAuthentication",
"rest_framework.authentication.SessionAuthentication",
),
At the end, SessionAuthentication
for me is only used in the django admin panel and 99% of the requests goes to the API that uses JWT auth.
- [Django]-How do I create a slug in Django?
- [Django]-Django: How can I create a multiple select form?
- [Django]-Django queries β id vs pk