Issue #3906
Updated by milan over 6 years ago
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:
<pre>
HTTP 400 Bad Request
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
{
"csrfmiddlewaretoken": [
"Unexpected field"
]
}
</pre>
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.
h3. 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":http://kylebebak.github.io/post/django-rest-framework-auth-csrf such as with a browser; "non-session authentication won't trigger the CSRF protection":http://www.django-rest-framework.org/api-guide/authentication/#sessionauthentication.
Unfortunately it seems the session-authentication is somehow mandatory or at least I wasn't able to just switch it off:
<pre>
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
</pre>
h3. Discussion
The session authentication is configured for particular Django application in @app/settings.py@:
<pre><code class="python">
MIDDLEWARE = [
...
django.middleware.csrf.CsrfViewMiddleware,
django.contrib.auth.middleware.AuthenticationMiddleware,
]
...
REST_FRAMEWORK = {
...
'DEFAULT_AUTHENTICATION_CLASSES': [
rest_framework.authentication.SessionAuthentication,
rest_framework.authentication.BasicAuthentication,
]
}
</code></pre>
DRF uses a custom authentication class "@SessionAuthentication@":https://github.com/encode/django-rest-framework/blob/version-2.4.x/rest_framework/authentication.py#L129 that in turn utilizes the Django middleware @CsrfViewMiddleware@ class thru the "@CSRFCheck@":https://github.com/encode/django-rest-framework/blob/version-2.4.x/rest_framework/authentication.py#L30 class, so the "@CsrfViewMiddleware:process_view@":https://github.com/django/django/blob/stable/2.1.x/django/middleware/csrf.py#L205 gets eventually triggered. The @request_csrf_token@ is then extracted from the "@request.POST.get('csrfmiddlewaretoken')@":https://github.com/django/django/blob/stable/2.1.x/django/middleware/csrf.py#L294 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":https://github.com/search?q=csrfmiddlewaretoken so often in fact that I can't confirm some of it being DRF/Django workarounds.