Project

Profile

Help

Issue #3906

closed

browsable API inserts a csrf token field into all form submissions

Added by dkliban@redhat.com over 6 years ago. Updated almost 5 years ago.

Status:
CLOSED - CURRENTRELEASE
Priority:
Normal
Assignee:
Category:
-
Sprint/Milestone:
Start date:
Due date:
Estimated time:
Severity:
2. Medium
Version:
Platform Release:
OS:
Triaged:
Yes
Groomed:
No
Sprint Candidate:
No
Tags:
Sprint:
Sprint 41
Quarter:

Description

Pulp's REST API validates that only acceptable fields are submitted with each request. The list of fields does not include the csrf token. As a result of this validation, the browsable API forms produce responses that look like this:

    HTTP 400 Bad Request
    Allow: GET, POST, HEAD, OPTIONS
    Content-Type: application/json
    Vary: Accept

    {
        "csrfmiddlewaretoken": [
            "Unexpected field"
        ]
    }

We need to investigate how to configure DRF to stop including this field with each form. Otherwise a fix from comment 3 would be appropriate.

Notes

To easily reproduce, navigate your browser to e.g http://localhost:8000/pulp/api/v3/repositories/ and create a repository by filling-in the create repository form.
This happens when session authentication is used such as with a browser; non-session authentication won't trigger the CSRF protection.
Unfortunately it seems the session-authentication is somehow mandatory or at least I wasn't able to just switch it off:

pulp: django.request:ERROR: Internal Server Error: /pulp/api/v3/repositories/
Traceback (most recent call last):
  File "/home/vagrant/.virtualenvs/pulp/lib64/python3.6/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "/home/vagrant/.virtualenvs/pulp/lib64/python3.6/site-packages/django/utils/deprecation.py", line 90, in __call__
    response = self.process_request(request)
  File "/home/vagrant/.virtualenvs/pulp/lib64/python3.6/site-packages/django/contrib/auth/middleware.py", line 23, in process_request
    ) % ("_CLASSES" if settings.MIDDLEWARE is None else "")
AssertionError: The Django authentication middleware requires session middleware to be installed. Edit your MIDDLEWARE setting to insert 'django.contrib.sessions.middleware.SessionMiddleware' before 'django.contrib.auth.middleware.AuthenticationMiddleware'.
[13/Aug/2018 13:15:14] "GET /pulp/api/v3/repositories/ HTTP/1.1" 500 69693

Discussion

The session authentication is configured for particular Django application in app/settings.py:

MIDDLEWARE = [
  ...
  django.middleware.csrf.CsrfViewMiddleware,
  django.contrib.auth.middleware.AuthenticationMiddleware,
]
...

REST_FRAMEWORK = {
  ...
  'DEFAULT_AUTHENTICATION_CLASSES': [
    rest_framework.authentication.SessionAuthentication,
    rest_framework.authentication.BasicAuthentication,
  ]
}

DRF uses a custom authentication class SessionAuthentication that in turn utilizes the Django middleware CsrfViewMiddleware class thru the CSRFCheck class, so the CsrfViewMiddleware:process_view gets eventually triggered. The request_csrf_token is then extracted from the request.POST.get('csrfmiddlewaretoken') form field, which is unset neither in the Django nor in the DRF middleware classes and the csrfmiddlewaretoken form field gets eventually propagated into a Pulp create object view.

Good news is we should be fine to just ignore it; "greping" over Github, this particular csrfmiddlewaretoken string shows quite often in the code so often in fact that I can't confirm some of it being DRF/Django workarounds.


Related issues

Related to Pulp - Issue #2970: REST API silently ignores object attributes that don't exist on the serializerCLOSED - CURRENTRELEASEmuattiyahActions

Also available in: Atom PDF