mirror of https://github.com/django/django.git
Refs #28215 -- Marked auth credentials as sensitive variables.
Co-authored-by: Collin Anderson <collin@onetencommunications.com>
This commit is contained in:
parent
cee93c6ba1
commit
4eb756793b
|
@ -7,6 +7,7 @@ from django.core.exceptions import ImproperlyConfigured, PermissionDenied
|
||||||
from django.middleware.csrf import rotate_token
|
from django.middleware.csrf import rotate_token
|
||||||
from django.utils.crypto import constant_time_compare
|
from django.utils.crypto import constant_time_compare
|
||||||
from django.utils.module_loading import import_string
|
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
|
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)
|
return _get_backends(return_tuples=False)
|
||||||
|
|
||||||
|
|
||||||
|
@sensitive_variables('credentials')
|
||||||
def _clean_credentials(credentials):
|
def _clean_credentials(credentials):
|
||||||
"""
|
"""
|
||||||
Clean a dictionary of credentials of potentially sensitive info before
|
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])
|
return get_user_model()._meta.pk.to_python(request.session[SESSION_KEY])
|
||||||
|
|
||||||
|
|
||||||
|
@sensitive_variables('credentials')
|
||||||
def authenticate(request=None, **credentials):
|
def authenticate(request=None, **credentials):
|
||||||
"""
|
"""
|
||||||
If the given credentials are valid, return a User object.
|
If the given credentials are valid, return a User object.
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
|
import sys
|
||||||
from datetime import date
|
from datetime import date
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
from django.contrib.auth import (
|
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.backends import BaseBackend, ModelBackend
|
||||||
from django.contrib.auth.hashers import MD5PasswordHasher
|
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.core.exceptions import ImproperlyConfigured, PermissionDenied
|
||||||
from django.http import HttpRequest
|
from django.http import HttpRequest
|
||||||
from django.test import (
|
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 django.views.decorators.debug import sensitive_variables
|
||||||
|
|
||||||
from .models import (
|
from .models import (
|
||||||
|
@ -633,6 +637,7 @@ class TypeErrorBackend:
|
||||||
Always raises TypeError.
|
Always raises TypeError.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@sensitive_variables('password')
|
||||||
def authenticate(self, request, username=None, password=None):
|
def authenticate(self, request, username=None, password=None):
|
||||||
raise TypeError
|
raise TypeError
|
||||||
|
|
||||||
|
@ -654,12 +659,50 @@ class AuthenticateTests(TestCase):
|
||||||
def setUpTestData(cls):
|
def setUpTestData(cls):
|
||||||
cls.user1 = User.objects.create_user('test', 'test@example.com', 'test')
|
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'])
|
@override_settings(AUTHENTICATION_BACKENDS=['auth_tests.test_auth_backends.TypeErrorBackend'])
|
||||||
def test_type_error_raised(self):
|
def test_type_error_raised(self):
|
||||||
"""A TypeError within a backend is propagated properly (#18171)."""
|
"""A TypeError within a backend is propagated properly (#18171)."""
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(TypeError):
|
||||||
authenticate(username='test', password='test')
|
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>'********************'</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>'********************'</pre></td></tr>',
|
||||||
|
html=True,
|
||||||
|
status_code=500,
|
||||||
|
)
|
||||||
|
|
||||||
@override_settings(AUTHENTICATION_BACKENDS=(
|
@override_settings(AUTHENTICATION_BACKENDS=(
|
||||||
'auth_tests.test_auth_backends.SkippedBackend',
|
'auth_tests.test_auth_backends.SkippedBackend',
|
||||||
'django.contrib.auth.backends.ModelBackend',
|
'django.contrib.auth.backends.ModelBackend',
|
||||||
|
|
Loading…
Reference in New Issue