Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fixed #18171 -- Checked signature of authenticate() to avoid supressi…

…ng 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.
  • Loading branch information...
commit b89c2a5d9eb70ca36629ef657c98e3371e9a5c4f 1 parent 5b889b2
@mgorny mgorny authored timgraham committed
View
6 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
View
29 django/contrib/auth/tests/test_auth_backends.py
@@ -480,3 +480,32 @@ def test_changed_backend_settings(self):
# 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')
Please sign in to comment.
Something went wrong with that request. Please try again.