mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Fixed #28699 -- Fixed CSRF validation with remote user middleware.
Ensured process_view() always accesses the CSRF token from the session or cookie, rather than the request, as rotate_token() may have been called by an authentication middleware during the process_request() phase.
This commit is contained in:
		
				
					committed by
					
						 Carlton Gibson
						Carlton Gibson
					
				
			
			
				
	
			
			
			
						parent
						
							bc1c034076
						
					
				
				
					commit
					f283ffaa84
				
			
							
								
								
									
										1
									
								
								AUTHORS
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								AUTHORS
									
									
									
									
									
								
							| @@ -201,6 +201,7 @@ answer newbie questions, and generally made Django that much better: | ||||
|     Colin Wood <cwood06@gmail.com> | ||||
|     Collin Anderson <cmawebsite@gmail.com> | ||||
|     Collin Grady <collin@collingrady.com> | ||||
|     Colton Hicks <coltonbhicks@gmail.com> | ||||
|     Craig Blaszczyk <masterjakul@gmail.com> | ||||
|     crankycoder@gmail.com | ||||
|     Curtis Maloney (FunkyBob) <curtis@tinbrain.net> | ||||
|   | ||||
| @@ -280,7 +280,10 @@ class CsrfViewMiddleware(MiddlewareMixin): | ||||
|                     reason = REASON_BAD_REFERER % referer.geturl() | ||||
|                     return self._reject(request, reason) | ||||
|  | ||||
|             csrf_token = request.META.get('CSRF_COOKIE') | ||||
|             # Access csrf_token via self._get_token() as rotate_token() may | ||||
|             # have been called by an authentication middleware during the | ||||
|             # process_request() phase. | ||||
|             csrf_token = self._get_token(request) | ||||
|             if csrf_token is None: | ||||
|                 # No CSRF cookie. For POST requests, we insist on a CSRF cookie, | ||||
|                 # and in this way we can avoid all CSRF attacks, including login | ||||
|   | ||||
| @@ -5,7 +5,8 @@ from django.contrib.auth import authenticate | ||||
| from django.contrib.auth.backends import RemoteUserBackend | ||||
| from django.contrib.auth.middleware import RemoteUserMiddleware | ||||
| from django.contrib.auth.models import User | ||||
| from django.test import TestCase, modify_settings, override_settings | ||||
| from django.middleware.csrf import _get_new_csrf_string, _mask_cipher_secret | ||||
| from django.test import Client, TestCase, modify_settings, override_settings | ||||
| from django.utils import timezone | ||||
|  | ||||
|  | ||||
| @@ -50,6 +51,35 @@ class RemoteUserTest(TestCase): | ||||
|         self.assertTrue(response.context['user'].is_anonymous) | ||||
|         self.assertEqual(User.objects.count(), num_users) | ||||
|  | ||||
|     def test_csrf_validation_passes_after_process_request_login(self): | ||||
|         """ | ||||
|         CSRF check must access the CSRF token from the session or cookie, | ||||
|         rather than the request, as rotate_token() may have been called by an | ||||
|         authentication middleware during the process_request() phase. | ||||
|         """ | ||||
|         csrf_client = Client(enforce_csrf_checks=True) | ||||
|         csrf_secret = _get_new_csrf_string() | ||||
|         csrf_token = _mask_cipher_secret(csrf_secret) | ||||
|         csrf_token_form = _mask_cipher_secret(csrf_secret) | ||||
|         headers = {self.header: 'fakeuser'} | ||||
|         data = {'csrfmiddlewaretoken': csrf_token_form} | ||||
|  | ||||
|         # Verify that CSRF is configured for the view | ||||
|         csrf_client.cookies.load({settings.CSRF_COOKIE_NAME: csrf_token}) | ||||
|         response = csrf_client.post('/remote_user/', **headers) | ||||
|         self.assertEqual(response.status_code, 403) | ||||
|         self.assertIn(b'CSRF verification failed.', response.content) | ||||
|  | ||||
|         # This request will call django.contrib.auth.login() which will call | ||||
|         # django.middleware.csrf.rotate_token() thus changing the value of | ||||
|         # request.META['CSRF_COOKIE'] from the user submitted value set by | ||||
|         # CsrfViewMiddleware.process_request() to the new csrftoken value set | ||||
|         # by rotate_token(). Csrf validation should still pass when the view is | ||||
|         # later processed by CsrfViewMiddleware.process_view() | ||||
|         csrf_client.cookies.load({settings.CSRF_COOKIE_NAME: csrf_token}) | ||||
|         response = csrf_client.post('/remote_user/', data, **headers) | ||||
|         self.assertEqual(response.status_code, 200) | ||||
|  | ||||
|     def test_unknown_user(self): | ||||
|         """ | ||||
|         Tests the case where the username passed in the header does not exist | ||||
|   | ||||
		Reference in New Issue
	
	Block a user