I am using Django Rest's browsable API to POST using Session Authentication, and am getting CSRF token missing, even though it was supplied. I am seeking advice on configuring my ModelViewSet
subclass so that this works.
Here's my viewset:
class TreeAPI(ModelViewSet):
authentication_classes = (SessionAuthentication,)
queryset = Tree.objects.get_roots()
parser_classes = (JSONParser, FormParser, MultiPartParser)
permission_classes = (IsAdminUser,)
throttle_classes = (TreeThrottle,)
serializer_class = TreeSerializer
I am able to use the DRF Browsable API to GET
this endpoint, but when I use it to POST
to this endpoint, I get a 403 with the message CSRF token missing or incorrect
.
When I set a breakpoint in the constructor to rest_framework.request.Request, I can see that the request passed in contains the needed csrfmiddleware
token:
In Django Rest's Request
class, POST
is actually a property:
@property
def POST(self):
if not _hasattr(self, '_data'):
self._load_data_and_files()
if is_form_media_type(self.content_type):
# self.data is an empty QueryDict!
return self.data
return QueryDict('', encoding=self._request._encoding)
request.POST
no longer contains the csrfmiddlewaretoken
key; it is stripped of all keys supplied with the form:
As a result, the parameter passed to rest_framework.authentication.SessionAuthentication.enforce_csrf(request)
which is then passed to django.middleware.csrf.CsrfViewMiddleware.process_view
does not find the csrfmiddlewaretoken
token:
if request.method == "POST":
request_csrf_token = request.POST.get('csrfmiddlewaretoken', '')
What can I check? What are the possible sources of error here?
Considerations
- not interested in disabling CSRF
- not interested in using token authentication
- am familiar with how to use CSRF tokens and the Django docs on them
- am familiar with Django REST's docs on CSRF tokens
- this is the built-in Django REST browsable API; haven't modified anything in UI
EDIT 1 - Middleware
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
)
EDIT 2 - versions of software - djangorestframework==3.3.3 - Django==1.9.8
EDIT 3 - possibly related issues at the git project
- 'request.data' empty when multipart form data POST in 3.3.x 3814
- Request.data empty when multipart/form-data POSTed 3951
EDIT 4 - possibly related stack overflow posts
- Having a POST'able API and Django's CSRF Middleware
- How to make a POST simple JSON using Django REST Framework? CSRF token missing or incorrect
- How to make a Django-Rest-Framework API that takes POST data?
- Django Rest Framework, ajax POST works but PATCH throws CSRF Failed: CSRF token missing or incorrect
- http://www.django-rest-framework.org/api-guide/parsers/#formparser