diff --git a/django/contrib/auth/__init__.py b/django/contrib/auth/__init__.py index afcff27ee90..550b60d14e9 100644 --- a/django/contrib/auth/__init__.py +++ b/django/contrib/auth/__init__.py @@ -20,10 +20,11 @@ def load_backend(path): return import_string(path)() -def get_backends(): +def _get_backends(return_tuples=False): backends = [] for backend_path in settings.AUTHENTICATION_BACKENDS: - backends.append(load_backend(backend_path)) + backend = load_backend(backend_path) + backends.append((backend, backend_path) if return_tuples else backend) if not backends: raise ImproperlyConfigured( 'No authentication backends have been defined. Does ' @@ -32,6 +33,10 @@ def get_backends(): return backends +def get_backends(): + return _get_backends(return_tuples=False) + + def _clean_credentials(credentials): """ Cleans a dictionary of credentials of potentially sensitive info before @@ -51,7 +56,7 @@ def authenticate(**credentials): """ If the given credentials are valid, return a User object. """ - for backend in get_backends(): + for backend, backend_path in _get_backends(return_tuples=True): try: inspect.getcallargs(backend.authenticate, **credentials) except TypeError: @@ -66,7 +71,7 @@ def authenticate(**credentials): if user is None: continue # Annotate the user object with the path of the backend. - user.backend = "%s.%s" % (backend.__module__, backend.__class__.__name__) + user.backend = backend_path return user # The credentials supplied are invalid to all backends, fire signal diff --git a/django/contrib/auth/tests/__init__.py b/django/contrib/auth/tests/__init__.py index 2c308642e52..bf9af5db455 100644 --- a/django/contrib/auth/tests/__init__.py +++ b/django/contrib/auth/tests/__init__.py @@ -1 +1,4 @@ # The password for the fixture data users is 'password' + +# For testing that auth backends can be referenced using a convenience import +from django.contrib.auth.tests.test_auth_backends import ImportedModelBackend # NOQA diff --git a/django/contrib/auth/tests/test_auth_backends.py b/django/contrib/auth/tests/test_auth_backends.py index 4845128ff08..65d9fde8f8b 100644 --- a/django/contrib/auth/tests/test_auth_backends.py +++ b/django/contrib/auth/tests/test_auth_backends.py @@ -8,7 +8,7 @@ from django.contrib.auth.tests.utils import skipIfCustomUser from django.contrib.auth.tests.custom_user import ExtensionUser, CustomPermissionsUser, CustomUser from django.contrib.contenttypes.models import ContentType from django.core.exceptions import ImproperlyConfigured, PermissionDenied -from django.contrib.auth import authenticate, get_user +from django.contrib.auth import authenticate, BACKEND_SESSION_KEY, get_user from django.http import HttpRequest from django.test import TestCase, override_settings from django.contrib.auth.hashers import MD5PasswordHasher @@ -608,3 +608,26 @@ class ImproperlyConfiguredUserModelTest(TestCase): request.session = self.client.session self.assertRaises(ImproperlyConfigured, get_user, request) + + +class ImportedModelBackend(ModelBackend): + pass + + +class ImportedBackendTests(TestCase): + """ + #23925 - The backend path added to the session should be the same + as the one defined in AUTHENTICATION_BACKENDS setting. + """ + + backend = 'django.contrib.auth.tests.ImportedModelBackend' + + @override_settings(AUTHENTICATION_BACKENDS=(backend, )) + def test_backend_path(self): + username = 'username' + password = 'password' + User.objects.create_user(username, 'email', password) + self.assertTrue(self.client.login(username=username, password=password)) + request = HttpRequest() + request.session = self.client.session + self.assertEqual(request.session[BACKEND_SESSION_KEY], self.backend)