summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--django/contrib/auth/backends.py3
-rw-r--r--tests/auth_tests/models/custom_user.py14
-rw-r--r--tests/auth_tests/test_auth_backends.py36
3 files changed, 53 insertions, 0 deletions
diff --git a/django/contrib/auth/backends.py b/django/contrib/auth/backends.py
index e72a18981c..0793a238d7 100644
--- a/django/contrib/auth/backends.py
+++ b/django/contrib/auth/backends.py
@@ -3,6 +3,7 @@ from asgiref.sync import sync_to_async
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Permission
from django.db.models import Exists, OuterRef, Q
+from django.views.decorators.debug import sensitive_variables
UserModel = get_user_model()
@@ -56,6 +57,7 @@ class ModelBackend(BaseBackend):
Authenticates against settings.AUTH_USER_MODEL.
"""
+ @sensitive_variables("password")
def authenticate(self, request, username=None, password=None, **kwargs):
if username is None:
username = kwargs.get(UserModel.USERNAME_FIELD)
@@ -71,6 +73,7 @@ class ModelBackend(BaseBackend):
if user.check_password(password) and self.user_can_authenticate(user):
return user
+ @sensitive_variables("password")
async def aauthenticate(self, request, username=None, password=None, **kwargs):
if username is None:
username = kwargs.get(UserModel.USERNAME_FIELD)
diff --git a/tests/auth_tests/models/custom_user.py b/tests/auth_tests/models/custom_user.py
index dac61f8e68..29dc42f645 100644
--- a/tests/auth_tests/models/custom_user.py
+++ b/tests/auth_tests/models/custom_user.py
@@ -143,3 +143,17 @@ with RemoveGroupsAndPermissions():
custom_objects = UserManager()
REQUIRED_FIELDS = AbstractUser.REQUIRED_FIELDS + ["date_of_birth"]
+
+
+class ErrorUserManager(BaseUserManager):
+ def get_by_natural_key(self, _):
+ raise TypeError
+
+ async def aget_by_natural_key(self, _):
+ raise TypeError
+
+
+with RemoveGroupsAndPermissions():
+
+ class ErrorAdminUser(AbstractUser):
+ custom_objects = ErrorUserManager()
diff --git a/tests/auth_tests/test_auth_backends.py b/tests/auth_tests/test_auth_backends.py
index 3ea6ff6a69..77eeed3d60 100644
--- a/tests/auth_tests/test_auth_backends.py
+++ b/tests/auth_tests/test_auth_backends.py
@@ -1146,6 +1146,42 @@ class AuthenticateTests(TestCase):
status_code=500,
)
+ @override_settings(AUTH_USER_MODEL="auth_tests.ErrorAdminUser")
+ def test_model_backend_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,
+ '<tr><td>password</td><td class="code">'
+ "<pre>&#39;********************&#39;</pre></td></tr>",
+ html=True,
+ status_code=500,
+ )
+
+ @override_settings(AUTH_USER_MODEL="auth_tests.ErrorAdminUser")
+ async def test_model_backend_async_authenticate_sensitive_variables(self):
+ try:
+ await aauthenticate(
+ 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,
+ '<tr><td>password</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