summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTamas Szabo <tszabo@ccg.murdoch.edu.au>2017-05-15 06:22:58 +0800
committerTim Graham <timograham@gmail.com>2017-05-15 08:15:18 -0400
commitd945b7e42a8d45cb13b1bd0420b420cf563482f1 (patch)
tree7b171da67e0ddfdad6e7ae8a4d33e416ff9ad4ce
parent84f6098aaf8d9cca521f7776134564b7f5ed704a (diff)
[1.11.x] Fixed #28207 -- Fixed contrib.auth.authenticate() if multiple auth backends don't accept a request.
Backport of 3008f30f194af386c354416be4c483f0f6b15f33 from master
-rw-r--r--django/contrib/auth/__init__.py65
-rw-r--r--docs/releases/1.11.2.txt3
-rw-r--r--tests/auth_tests/test_auth_backends_deprecation.py18
3 files changed, 55 insertions, 31 deletions
diff --git a/django/contrib/auth/__init__.py b/django/contrib/auth/__init__.py
index 426bd6982b..94153d243d 100644
--- a/django/contrib/auth/__init__.py
+++ b/django/contrib/auth/__init__.py
@@ -66,38 +66,8 @@ 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):
- args = (request,)
- # Does the backend accept a request argument?
try:
- inspect.getcallargs(backend.authenticate, request, **credentials)
- except TypeError:
- args = ()
- # Does the backend accept a request keyword argument?
- try:
- inspect.getcallargs(backend.authenticate, request=request, **credentials)
- except TypeError:
- # Does the backend accept credentials without request?
- try:
- inspect.getcallargs(backend.authenticate, **credentials)
- except TypeError:
- # This backend doesn't accept these credentials as arguments. Try the next one.
- continue
- else:
- warnings.warn(
- "Update %s.authenticate() to accept a positional "
- "`request` argument." % backend_path,
- RemovedInDjango21Warning
- )
- else:
- credentials['request'] = request
- warnings.warn(
- "In %s.authenticate(), move the `request` keyword argument "
- "to the first positional argument." % backend_path,
- RemovedInDjango21Warning
- )
-
- try:
- user = backend.authenticate(*args, **credentials)
+ user = _authenticate_with_backend(backend, backend_path, request, **credentials)
except PermissionDenied:
# This backend says to stop in our tracks - this user should not be allowed in at all.
break
@@ -111,6 +81,39 @@ def authenticate(request=None, **credentials):
user_login_failed.send(sender=__name__, credentials=_clean_credentials(credentials), request=request)
+def _authenticate_with_backend(backend, backend_path, request, **credentials):
+ args = (request,)
+ # Does the backend accept a request argument?
+ try:
+ inspect.getcallargs(backend.authenticate, request, **credentials)
+ except TypeError:
+ args = ()
+ # Does the backend accept a request keyword argument?
+ try:
+ inspect.getcallargs(backend.authenticate, request=request, **credentials)
+ except TypeError:
+ # Does the backend accept credentials without request?
+ try:
+ inspect.getcallargs(backend.authenticate, **credentials)
+ except TypeError:
+ # This backend doesn't accept these credentials as arguments. Try the next one.
+ return None
+ else:
+ warnings.warn(
+ "Update %s.authenticate() to accept a positional "
+ "`request` argument." % backend_path,
+ RemovedInDjango21Warning
+ )
+ else:
+ credentials['request'] = request
+ warnings.warn(
+ "In %s.authenticate(), move the `request` keyword argument "
+ "to the first positional argument." % backend_path,
+ RemovedInDjango21Warning
+ )
+ return backend.authenticate(*args, **credentials)
+
+
def login(request, user, backend=None):
"""
Persist a user id and a backend in the request. This way a user doesn't
diff --git a/docs/releases/1.11.2.txt b/docs/releases/1.11.2.txt
index 558b3e40c3..6831f60cef 100644
--- a/docs/releases/1.11.2.txt
+++ b/docs/releases/1.11.2.txt
@@ -20,3 +20,6 @@ Bugfixes
(:ticket:`28142`).
* Fixed regression causing pickling of model fields to crash (:ticket:`28188`).
+
+* Fixed ``django.contrib.auth.authenticate()`` when multiple authentication
+ backends don't accept a positional ``request`` argument (:ticket:`28207`).
diff --git a/tests/auth_tests/test_auth_backends_deprecation.py b/tests/auth_tests/test_auth_backends_deprecation.py
index 0d45fee7a4..7ee53a0bc6 100644
--- a/tests/auth_tests/test_auth_backends_deprecation.py
+++ b/tests/auth_tests/test_auth_backends_deprecation.py
@@ -50,3 +50,21 @@ class AcceptsRequestBackendTest(SimpleTestCase):
"In %s.authenticate(), move the `request` keyword argument to the "
"first positional argument." % self.request_not_positional_backend
)
+
+ @override_settings(AUTHENTICATION_BACKENDS=[request_not_positional_backend, no_request_backend])
+ def test_both_types_of_deprecation_warning(self):
+ with warnings.catch_warnings(record=True) as warns:
+ warnings.simplefilter('always')
+ authenticate(mock_request, username='username', password='pass')
+
+ self.assertEqual(len(warns), 2)
+ self.assertEqual(
+ str(warns[0].message),
+ "In %s.authenticate(), move the `request` keyword argument to the "
+ "first positional argument." % self.request_not_positional_backend
+ )
+ self.assertEqual(
+ str(warns[1].message),
+ "Update %s.authenticate() to accept a positional `request` "
+ "argument." % self.no_request_backend
+ )