summaryrefslogtreecommitdiff
path: root/django
diff options
context:
space:
mode:
authorPreston Holmes <preston@ptone.com>2014-07-27 21:54:29 -0700
committerTim Graham <timograham@gmail.com>2014-08-20 14:39:40 -0400
commit5307ce565fbedb9cc27cbe7c757b41a00438d37c (patch)
tree295d07a06ed1cefb7a695e764c96420e6aebda81 /django
parent0d8d30b7ddfe83ab03120f4560c7aa153f4d0ed1 (diff)
Fixed #23066 -- Modified RemoteUserMiddleware to logout on REMOTE_USER change.
This is a security fix. Disclosure following shortly.
Diffstat (limited to 'django')
-rw-r--r--django/contrib/auth/middleware.py28
-rw-r--r--django/contrib/auth/tests/test_remote_user.py18
2 files changed, 38 insertions, 8 deletions
diff --git a/django/contrib/auth/middleware.py b/django/contrib/auth/middleware.py
index b2f392262a..b34da60299 100644
--- a/django/contrib/auth/middleware.py
+++ b/django/contrib/auth/middleware.py
@@ -76,14 +76,7 @@ class RemoteUserMiddleware(object):
# authenticated remote-user, or return (leaving request.user set to
# AnonymousUser by the AuthenticationMiddleware).
if request.user.is_authenticated():
- try:
- stored_backend = load_backend(request.session.get(
- auth.BACKEND_SESSION_KEY, ''))
- if isinstance(stored_backend, RemoteUserBackend):
- auth.logout(request)
- except ImportError:
- # backend failed to load
- auth.logout(request)
+ self._remove_invalid_user(request)
return
# If the user is already authenticated and that user is the user we are
# getting passed in the headers, then the correct user is already
@@ -91,6 +84,11 @@ class RemoteUserMiddleware(object):
if request.user.is_authenticated():
if request.user.get_username() == self.clean_username(username, request):
return
+ else:
+ # An authenticated user is associated with the request, but
+ # it does not match the authorized user in the header.
+ self._remove_invalid_user(request)
+
# We are seeing this user for the first time in this session, attempt
# to authenticate the user.
user = auth.authenticate(remote_user=username)
@@ -112,3 +110,17 @@ class RemoteUserMiddleware(object):
except AttributeError: # Backend has no clean_username method.
pass
return username
+
+ def _remove_invalid_user(self, request):
+ """
+ Removes the current authenticated user in the request which is invalid
+ but only if the user is authenticated via the RemoteUserBackend.
+ """
+ try:
+ stored_backend = load_backend(request.session.get(auth.BACKEND_SESSION_KEY, ''))
+ except ImportError:
+ # backend failed to load
+ auth.logout(request)
+ else:
+ if isinstance(stored_backend, RemoteUserBackend):
+ auth.logout(request)
diff --git a/django/contrib/auth/tests/test_remote_user.py b/django/contrib/auth/tests/test_remote_user.py
index 2ccfd6e6fa..790e5d0d53 100644
--- a/django/contrib/auth/tests/test_remote_user.py
+++ b/django/contrib/auth/tests/test_remote_user.py
@@ -125,6 +125,24 @@ class RemoteUserTest(TestCase):
response = self.client.get('/remote_user/')
self.assertEqual(response.context['user'].username, 'modeluser')
+ def test_user_switch_forces_new_login(self):
+ """
+ Tests that if the username in the header changes between requests
+ that the original user is logged out
+ """
+ User.objects.create(username='knownuser')
+ # Known user authenticates
+ response = self.client.get('/remote_user/',
+ **{self.header: self.known_user})
+ self.assertEqual(response.context['user'].username, 'knownuser')
+ # During the session, the REMOTE_USER changes to a different user.
+ response = self.client.get('/remote_user/',
+ **{self.header: "newnewuser"})
+ # Ensure that the current user is not the prior remote_user
+ # In backends that create a new user, username is "newnewuser"
+ # In backends that do not create new users, it is '' (anonymous user)
+ self.assertNotEqual(response.context['user'].username, 'knownuser')
+
def tearDown(self):
"""Restores settings to avoid breaking other tests."""
settings.MIDDLEWARE_CLASSES = self.curr_middleware