Fixed #26480 -- Fixed crash of contrib.auth.authenticate() on decorated authenticate() methods of authentication backends.

The Signature API (PEP 362) has better support for decorated functions
(by default, it follows the __wrapped__ attribute set by
functools.wraps for example).
This commit is contained in:
Baptiste Mispelon 2019-12-09 17:50:28 +01:00 committed by Mariusz Felisiak
parent 23af086665
commit 3df3c5e670
2 changed files with 16 additions and 1 deletions

View File

@ -63,8 +63,9 @@ def authenticate(request=None, **credentials):
If the given credentials are valid, return a User object. If the given credentials are valid, return a User object.
""" """
for backend, backend_path in _get_backends(return_tuples=True): for backend, backend_path in _get_backends(return_tuples=True):
backend_signature = inspect.signature(backend.authenticate)
try: try:
inspect.getcallargs(backend.authenticate, request, **credentials) backend_signature.bind(request, **credentials)
except TypeError: except TypeError:
# This backend doesn't accept these credentials as arguments. Try the next one. # This backend doesn't accept these credentials as arguments. Try the next one.
continue continue

View File

@ -13,6 +13,7 @@ from django.http import HttpRequest
from django.test import ( from django.test import (
SimpleTestCase, TestCase, modify_settings, override_settings, SimpleTestCase, TestCase, modify_settings, override_settings,
) )
from django.views.decorators.debug import sensitive_variables
from .models import ( from .models import (
CustomPermissionsUser, CustomUser, CustomUserWithoutIsActiveField, CustomPermissionsUser, CustomUser, CustomUserWithoutIsActiveField,
@ -642,6 +643,12 @@ class SkippedBackend:
pass pass
class SkippedBackendWithDecoratedMethod:
@sensitive_variables()
def authenticate(self):
pass
class AuthenticateTests(TestCase): class AuthenticateTests(TestCase):
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
@ -664,6 +671,13 @@ class AuthenticateTests(TestCase):
""" """
self.assertEqual(authenticate(username='test', password='test'), self.user1) self.assertEqual(authenticate(username='test', password='test'), self.user1)
@override_settings(AUTHENTICATION_BACKENDS=(
'auth_tests.test_auth_backends.SkippedBackendWithDecoratedMethod',
'django.contrib.auth.backends.ModelBackend',
))
def test_skips_backends_with_decorated_method(self):
self.assertEqual(authenticate(username='test', password='test'), self.user1)
class ImproperlyConfiguredUserModelTest(TestCase): class ImproperlyConfiguredUserModelTest(TestCase):
""" """