0

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:

enter image description here

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:

empty QueryDict

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

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

Community
  • 1
  • 1
Myer
  • 3,434
  • 1
  • 34
  • 46
  • That's strange. What's your middleware settings ? Maybe something's missing there too. – Linovia Mar 04 '17 at 08:52
  • @Linovia, I don't think that's the case, since I've verified that the CSRF cookie is sent correctly. Take a look at the 2017-03-06 edit, anyway, though. – Myer Mar 06 '17 at 13:47
  • Are you able to do the request with postman or curl? Have you customized the viewset in any way? Also, why are you using all three parsers? – Borko Kovacev Mar 06 '17 at 16:28

1 Answers1

0

This problem does not manifest in djangorestframework==3.5.4. See http://www.django-rest-framework.org/topics/release-notes/; I have a feeling this was fixed after 3.3.x.

Myer
  • 3,434
  • 1
  • 34
  • 46