diff --git a/django/contrib/auth/__init__.py b/django/contrib/auth/__init__.py index 6d99aa0c9b..09db690b5c 100644 --- a/django/contrib/auth/__init__.py +++ b/django/contrib/auth/__init__.py @@ -63,8 +63,9 @@ def authenticate(request=None, **credentials): If the given credentials are valid, return a User object. """ for backend, backend_path in _get_backends(return_tuples=True): + backend_signature = inspect.signature(backend.authenticate) try: - inspect.getcallargs(backend.authenticate, request, **credentials) + backend_signature.bind(request, **credentials) except TypeError: # This backend doesn't accept these credentials as arguments. Try the next one. continue diff --git a/tests/auth_tests/test_auth_backends.py b/tests/auth_tests/test_auth_backends.py index 92c60af7d6..b6aa1a2833 100644 --- a/tests/auth_tests/test_auth_backends.py +++ b/tests/auth_tests/test_auth_backends.py @@ -13,6 +13,7 @@ from django.http import HttpRequest from django.test import ( SimpleTestCase, TestCase, modify_settings, override_settings, ) +from django.views.decorators.debug import sensitive_variables from .models import ( CustomPermissionsUser, CustomUser, CustomUserWithoutIsActiveField, @@ -642,6 +643,12 @@ class SkippedBackend: pass +class SkippedBackendWithDecoratedMethod: + @sensitive_variables() + def authenticate(self): + pass + + class AuthenticateTests(TestCase): @classmethod def setUpTestData(cls): @@ -664,6 +671,13 @@ class AuthenticateTests(TestCase): """ 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): """