summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichał Górny <mgorny@gentoo.org>2013-08-23 17:49:42 +0200
committerTim Graham <timograham@gmail.com>2013-08-28 07:51:45 -0400
commitb89c2a5d9eb70ca36629ef657c98e3371e9a5c4f (patch)
tree3fc16e81d98696e058cfba1a5d3790863604bc7f
parent5b889b2408eeaf72f45d8f97c114d8ba9f540726 (diff)
Fixed #18171 -- Checked signature of authenticate() to avoid supressing TypeErrors.
The current auth backend code catches TypeError to detect backends that do not support specified argumetnts. As a result, any TypeErrors raised within the actual backend code are silenced. In Python 2.7+ and 3.2+ this can be avoided by using inspect.getcallargs(). With this method, we can test whether arguments match the signature without actually calling the function. Thanks David Eyk for the report.
-rw-r--r--django/contrib/auth/__init__.py6
-rw-r--r--django/contrib/auth/tests/test_auth_backends.py29
2 files changed, 34 insertions, 1 deletions
diff --git a/django/contrib/auth/__init__.py b/django/contrib/auth/__init__.py
index 2f620a34fe..4ef5c0b2cd 100644
--- a/django/contrib/auth/__init__.py
+++ b/django/contrib/auth/__init__.py
@@ -1,3 +1,4 @@
+import inspect
import re
from django.conf import settings
@@ -46,10 +47,13 @@ def authenticate(**credentials):
"""
for backend in get_backends():
try:
- user = backend.authenticate(**credentials)
+ inspect.getcallargs(backend.authenticate, **credentials)
except TypeError:
# This backend doesn't accept these credentials as arguments. Try the next one.
continue
+
+ try:
+ user = backend.authenticate(**credentials)
except PermissionDenied:
# This backend says to stop in our tracks - this user should not be allowed in at all.
return None
diff --git a/django/contrib/auth/tests/test_auth_backends.py b/django/contrib/auth/tests/test_auth_backends.py
index 4e83d786cf..4afe7c026c 100644
--- a/django/contrib/auth/tests/test_auth_backends.py
+++ b/django/contrib/auth/tests/test_auth_backends.py
@@ -480,3 +480,32 @@ class ChangedBackendSettingsTest(TestCase):
# anonymous as the backend is not longer available.
self.assertIsNotNone(user)
self.assertTrue(user.is_anonymous())
+
+
+class TypeErrorBackend(object):
+ """
+ Always raises TypeError.
+ """
+ supports_object_permissions = True
+ supports_anonymous_user = True
+ supports_inactive_user = True
+
+ def authenticate(self, username=None, password=None):
+ raise TypeError
+
+
+@skipIfCustomUser
+class TypeErrorBackendTest(TestCase):
+ """
+ Tests that a TypeError within a backend is propagated properly.
+
+ Regression test for ticket #18171
+ """
+ backend = 'django.contrib.auth.tests.test_auth_backends.TypeErrorBackend'
+
+ def setUp(self):
+ self.user1 = User.objects.create_user('test', 'test@example.com', 'test')
+
+ @override_settings(AUTHENTICATION_BACKENDS=(backend, ))
+ def test_type_error_raised(self):
+ self.assertRaises(TypeError, authenticate, username='test', password='test')