Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 19 additions & 11 deletions django/contrib/auth/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ def process_request(self, request):
" authentication middleware to be installed. Edit your"
" MIDDLEWARE setting to insert"
" 'django.contrib.auth.middleware.AuthenticationMiddleware'"
" before the RemoteUserMiddleware class."
f" before the {self.__class__.__name__} class."
)
try:
username = request.META[self.header]
Expand All @@ -164,24 +164,23 @@ def process_request(self, request):
# to authenticate the user.
user = auth.authenticate(request, remote_user=username)
if user:
# User is valid. Set request.user and persist user in the session
# by logging the user in.
request.user = user
# User is valid. Persist the user in the session by logging the
# user in.
auth.login(request, user)

async def __acall__(self, request):
await self.aprocess_request(request)
return await self.get_response(request)

async def aprocess_request(self, request):
# AuthenticationMiddleware is required so that request.user exists.
if not hasattr(request, "user"):
# AuthenticationMiddleware is required so that request.auser exists.
if not hasattr(request, "auser"):
raise ImproperlyConfigured(
"The Django remote user auth middleware requires the"
" authentication middleware to be installed. Edit your"
" MIDDLEWARE setting to insert"
" 'django.contrib.auth.middleware.AuthenticationMiddleware'"
" before the RemoteUserMiddleware class."
f" before the {self.__class__.__name__} class."
)
try:
username = request.META["HTTP_" + self.header]
Expand All @@ -199,7 +198,7 @@ async def aprocess_request(self, request):
# getting passed in the headers, then the correct user is already
# persisted in the session and we don't need to continue.
if user.is_authenticated:
if user.get_username() == self.clean_username(username, request):
if user.get_username() == await self.aclean_username(username, request):
return
else:
# An authenticated user is associated with the request, but
Expand All @@ -210,9 +209,8 @@ async def aprocess_request(self, request):
# to authenticate the user.
user = await auth.aauthenticate(request, remote_user=username)
if user:
# User is valid. Set request.user and persist user in the session
# by logging the user in.
request.user = user
# User is valid. Persist the user in the session by logging the
# user in.
await auth.alogin(request, user)

def clean_username(self, username, request):
Expand All @@ -228,6 +226,16 @@ def clean_username(self, username, request):
pass
return username

async def aclean_username(self, username, request):
"""See clean_username."""
backend_str = await request.session.aget(auth.BACKEND_SESSION_KEY)
backend = auth.load_backend(backend_str)
try:
username = backend.clean_username(username)
except AttributeError: # Backend has no clean_username method.
pass
return username

def _remove_invalid_user(self, request):
"""
Remove the current authenticated user in the request which is invalid
Expand Down
79 changes: 79 additions & 0 deletions tests/auth_tests/test_remote_user.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from django.contrib.auth.backends import RemoteUserBackend
from django.contrib.auth.middleware import RemoteUserMiddleware
from django.contrib.auth.models import User
from django.core.exceptions import ImproperlyConfigured
from django.middleware.csrf import _get_new_csrf_string, _mask_cipher_secret
from django.test import (
AsyncClient,
Expand Down Expand Up @@ -389,6 +390,13 @@ def configure_user(self, request, user, created=True):
user.save()
return user

async def aconfigure_user(self, request, user, created=True):
user.email = request.META.get("HTTP_" + RemoteUserTest.email_header, "")
if not created:
user.last_name = user.username
await user.asave()
return user


class RemoteUserCustomTest(RemoteUserTest):
"""
Expand Down Expand Up @@ -435,6 +443,32 @@ def test_unknown_user(self):
newuser = User.objects.get(username="newuser")
self.assertEqual(newuser.email, "user@example.com")

async def test_known_user_async(self):
"""See test_known_user."""
await super().test_known_user_async()
knownuser = await User.objects.aget(username="knownuser")
knownuser2 = await User.objects.aget(username="knownuser2")
self.assertEqual(knownuser.email, "")
self.assertEqual(knownuser2.email, "")
self.assertEqual(knownuser.last_name, "knownuser")
self.assertEqual(knownuser2.last_name, "knownuser2")

async def test_unknown_user_async(self):
num_users = await User.objects.acount()
response = await self.async_client.get(
"/remote_user/",
**{
self.header: "newuser",
self.email_header: "user@example.com",
},
)
self.assertEqual(response.context["user"].username, "newuser")
self.assertEqual(response.context["user"].email, "user@example.com")
self.assertEqual(response.context["user"].last_name, "")
self.assertEqual(await User.objects.acount(), num_users + 1)
newuser = await User.objects.aget(username="newuser")
self.assertEqual(newuser.email, "user@example.com")


class CustomHeaderMiddleware(RemoteUserMiddleware):
"""
Expand Down Expand Up @@ -489,3 +523,48 @@ async def test_header_disappears_async(self):
response = await self.async_client.get("/remote_user/")
self.assertFalse(response.context["user"].is_anonymous)
self.assertEqual(response.context["user"].username, "knownuser")


@override_settings(ROOT_URLCONF="auth_tests.urls")
class RemoteUserImproperlyConfigured(TestCase):
msg = (
"The Django remote user auth middleware requires the authentication middleware "
"to be installed. Edit your MIDDLEWARE setting to insert 'django.contrib.auth."
"middleware.AuthenticationMiddleware' before the %s class."
)

@override_settings(
MIDDLEWARE=["django.contrib.auth.middleware.RemoteUserMiddleware"]
)
def test_improperly_configured_message_remote_user(self):
with self.assertRaisesMessage(
ImproperlyConfigured, self.msg % "RemoteUserMiddleware"
):
self.client.get("/remote_user/")

@override_settings(
MIDDLEWARE=["django.contrib.auth.middleware.PersistentRemoteUserMiddleware"]
)
def test_improperly_configured_message_persistent_remote_user(self):
with self.assertRaisesMessage(
ImproperlyConfigured, self.msg % "PersistentRemoteUserMiddleware"
):
self.client.get("/remote_user/")

@override_settings(
MIDDLEWARE=["django.contrib.auth.middleware.RemoteUserMiddleware"]
)
async def test_improperly_configured_message_remote_user_async(self):
with self.assertRaisesMessage(
ImproperlyConfigured, self.msg % "RemoteUserMiddleware"
):
await self.async_client.get("/remote_user/")

@override_settings(
MIDDLEWARE=["django.contrib.auth.middleware.PersistentRemoteUserMiddleware"]
)
async def test_improperly_configured_message_persistent_remote_user_async(self):
with self.assertRaisesMessage(
ImproperlyConfigured, self.msg % "PersistentRemoteUserMiddleware"
):
await self.async_client.get("/remote_user/")
Loading