summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--django/contrib/auth/__init__.py3
-rw-r--r--tests/auth_tests/test_auth_backends.py47
2 files changed, 48 insertions, 2 deletions
diff --git a/django/contrib/auth/__init__.py b/django/contrib/auth/__init__.py
index 662137e595..cad8eff149 100644
--- a/django/contrib/auth/__init__.py
+++ b/django/contrib/auth/__init__.py
@@ -7,6 +7,7 @@ from django.core.exceptions import ImproperlyConfigured, PermissionDenied
from django.middleware.csrf import rotate_token
from django.utils.crypto import constant_time_compare
from django.utils.module_loading import import_string
+from django.views.decorators.debug import sensitive_variables
from .signals import user_logged_in, user_logged_out, user_login_failed
@@ -37,6 +38,7 @@ def get_backends():
return _get_backends(return_tuples=False)
+@sensitive_variables('credentials')
def _clean_credentials(credentials):
"""
Clean a dictionary of credentials of potentially sensitive info before
@@ -58,6 +60,7 @@ def _get_user_session_key(request):
return get_user_model()._meta.pk.to_python(request.session[SESSION_KEY])
+@sensitive_variables('credentials')
def authenticate(request=None, **credentials):
"""
If the given credentials are valid, return a User object.
diff --git a/tests/auth_tests/test_auth_backends.py b/tests/auth_tests/test_auth_backends.py
index b6aa1a2833..d01d0b6526 100644
--- a/tests/auth_tests/test_auth_backends.py
+++ b/tests/auth_tests/test_auth_backends.py
@@ -1,8 +1,10 @@
+import sys
from datetime import date
from unittest import mock
from django.contrib.auth import (
- BACKEND_SESSION_KEY, SESSION_KEY, authenticate, get_user, signals,
+ BACKEND_SESSION_KEY, SESSION_KEY, _clean_credentials, authenticate,
+ get_user, signals,
)
from django.contrib.auth.backends import BaseBackend, ModelBackend
from django.contrib.auth.hashers import MD5PasswordHasher
@@ -11,8 +13,10 @@ from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ImproperlyConfigured, PermissionDenied
from django.http import HttpRequest
from django.test import (
- SimpleTestCase, TestCase, modify_settings, override_settings,
+ RequestFactory, SimpleTestCase, TestCase, modify_settings,
+ override_settings,
)
+from django.views.debug import technical_500_response
from django.views.decorators.debug import sensitive_variables
from .models import (
@@ -633,6 +637,7 @@ class TypeErrorBackend:
Always raises TypeError.
"""
+ @sensitive_variables('password')
def authenticate(self, request, username=None, password=None):
raise TypeError
@@ -654,12 +659,50 @@ class AuthenticateTests(TestCase):
def setUpTestData(cls):
cls.user1 = User.objects.create_user('test', 'test@example.com', 'test')
+ def setUp(self):
+ self.sensitive_password = 'mypassword'
+
@override_settings(AUTHENTICATION_BACKENDS=['auth_tests.test_auth_backends.TypeErrorBackend'])
def test_type_error_raised(self):
"""A TypeError within a backend is propagated properly (#18171)."""
with self.assertRaises(TypeError):
authenticate(username='test', password='test')
+ @override_settings(AUTHENTICATION_BACKENDS=['auth_tests.test_auth_backends.TypeErrorBackend'])
+ def test_authenticate_sensitive_variables(self):
+ try:
+ authenticate(username='testusername', password=self.sensitive_password)
+ except TypeError:
+ exc_info = sys.exc_info()
+ rf = RequestFactory()
+ response = technical_500_response(rf.get('/'), *exc_info)
+ self.assertNotContains(response, self.sensitive_password, status_code=500)
+ self.assertContains(response, 'TypeErrorBackend', status_code=500)
+ self.assertContains(
+ response,
+ '<tr><td>credentials</td><td class="code">'
+ '<pre>&#39;********************&#39;</pre></td></tr>',
+ html=True,
+ status_code=500,
+ )
+
+ def test_clean_credentials_sensitive_variables(self):
+ try:
+ # Passing in a list to cause an exception
+ _clean_credentials([1, self.sensitive_password])
+ except TypeError:
+ exc_info = sys.exc_info()
+ rf = RequestFactory()
+ response = technical_500_response(rf.get('/'), *exc_info)
+ self.assertNotContains(response, self.sensitive_password, status_code=500)
+ self.assertContains(
+ response,
+ '<tr><td>credentials</td><td class="code">'
+ '<pre>&#39;********************&#39;</pre></td></tr>',
+ html=True,
+ status_code=500,
+ )
+
@override_settings(AUTHENTICATION_BACKENDS=(
'auth_tests.test_auth_backends.SkippedBackend',
'django.contrib.auth.backends.ModelBackend',