From 81fa4b4f757dc72e725ac031fd5c30f21e9945d4 Mon Sep 17 00:00:00 2001 From: Craig de Stigter Date: Tue, 7 Aug 2018 19:18:56 +1200 Subject: [PATCH] Fix CSRF cookie check failure when using session auth with django 1.11.6+ (#6113) Test included. Fixes #6088 --- rest_framework/authentication.py | 5 ++++- tests/test_authentication.py | 21 +++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/rest_framework/authentication.py b/rest_framework/authentication.py index 4b9fd6ed5..25150d525 100644 --- a/rest_framework/authentication.py +++ b/rest_framework/authentication.py @@ -135,7 +135,10 @@ class SessionAuthentication(BaseAuthentication): """ Enforce CSRF validation for session based authentication. """ - reason = CSRFCheck().process_view(request, None, (), {}) + check = CSRFCheck() + # populates request.META['CSRF_COOKIE'], which is used in process_view() + check.process_request(request) + reason = check.process_view(request, None, (), {}) if reason: # CSRF failed, bail with explicit error message raise exceptions.PermissionDenied('CSRF Failed: %s' % reason) diff --git a/tests/test_authentication.py b/tests/test_authentication.py index c08ea6970..f2714acb5 100644 --- a/tests/test_authentication.py +++ b/tests/test_authentication.py @@ -5,6 +5,7 @@ from __future__ import unicode_literals import base64 import pytest +from django.conf import settings from django.conf.urls import include, url from django.contrib.auth.models import User from django.db import models @@ -202,6 +203,26 @@ class SessionAuthTests(TestCase): response = self.csrf_client.post('/session/', {'example': 'example'}) assert response.status_code == status.HTTP_403_FORBIDDEN + def test_post_form_session_auth_passing_csrf(self): + """ + Ensure POSTing form over session authentication with CSRF token succeeds. + Regression test for #6088 + """ + from django.middleware.csrf import _get_new_csrf_token + + self.csrf_client.login(username=self.username, password=self.password) + + # Set the csrf_token cookie so that CsrfViewMiddleware._get_token() works + token = _get_new_csrf_token() + self.csrf_client.cookies[settings.CSRF_COOKIE_NAME] = token + + # Post the token matching the cookie value + response = self.csrf_client.post('/session/', { + 'example': 'example', + 'csrfmiddlewaretoken': token, + }) + assert response.status_code == status.HTTP_200_OK + def test_post_form_session_auth_passing(self): """ Ensure POSTing form over session authentication with logged in