+52
-3
lines changedFilter options
+52
-3
lines changed Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
1
1
from django.contrib import auth
2
+
from django.contrib.auth.backends import RemoteUserBackend
2
3
from django.core.exceptions import ImproperlyConfigured
3
4
from django.utils.functional import SimpleLazyObject
4
5
@@ -47,16 +48,23 @@ def process_request(self, request):
47
48
try:
48
49
username = request.META[self.header]
49
50
except KeyError:
50
-
# If specified header doesn't exist then return (leaving
51
-
# request.user set to AnonymousUser by the
52
-
# AuthenticationMiddleware).
51
+
# If specified header doesn't exist then remove any existing
52
+
# authenticated remote-user, or return (leaving request.user set to
53
+
# AnonymousUser by the AuthenticationMiddleware).
54
+
if request.user.is_authenticated():
55
+
self._remove_invalid_user(request)
53
56
return
54
57
# If the user is already authenticated and that user is the user we are
55
58
# getting passed in the headers, then the correct user is already
56
59
# persisted in the session and we don't need to continue.
57
60
if request.user.is_authenticated():
58
61
if request.user.username == self.clean_username(username, request):
59
62
return
63
+
else:
64
+
# An authenticated user is associated with the request, but
65
+
# it does not match the authorized user in the header.
66
+
self._remove_invalid_user(request)
67
+
60
68
# We are seeing this user for the first time in this session, attempt
61
69
# to authenticate the user.
62
70
user = auth.authenticate(remote_user=username)
@@ -78,3 +86,17 @@ def clean_username(self, username, request):
78
86
except AttributeError: # Backend has no clean_username method.
79
87
pass
80
88
return username
89
+
90
+
def _remove_invalid_user(self, request):
91
+
"""
92
+
Removes the current authenticated user in the request which is invalid
93
+
but only if the user is authenticated via the RemoteUserBackend.
94
+
"""
95
+
try:
96
+
stored_backend = auth.load_backend(request.session.get(auth.BACKEND_SESSION_KEY, ''))
97
+
except ImproperlyConfigured:
98
+
# backend failed to load
99
+
auth.logout(request)
100
+
else:
101
+
if isinstance(stored_backend, RemoteUserBackend):
102
+
auth.logout(request)
Original file line number Diff line number Diff line change
@@ -95,6 +95,24 @@ def test_last_login(self):
95
95
response = self.client.get('/remote_user/', REMOTE_USER=self.known_user)
96
96
self.assertEqual(default_login, response.context['user'].last_login)
97
97
98
+
def test_user_switch_forces_new_login(self):
99
+
"""
100
+
Tests that if the username in the header changes between requests
101
+
that the original user is logged out
102
+
"""
103
+
User.objects.create(username='knownuser')
104
+
# Known user authenticates
105
+
response = self.client.get('/remote_user/',
106
+
**{'REMOTE_USER': self.known_user})
107
+
self.assertEqual(response.context['user'].username, 'knownuser')
108
+
# During the session, the REMOTE_USER changes to a different user.
109
+
response = self.client.get('/remote_user/',
110
+
**{'REMOTE_USER': "newnewuser"})
111
+
# Ensure that the current user is not the prior remote_user
112
+
# In backends that create a new user, username is "newnewuser"
113
+
# In backends that do not create new users, it is '' (anonymous user)
114
+
self.assertNotEqual(response.context['user'].username, 'knownuser')
115
+
98
116
def tearDown(self):
99
117
"""Restores settings to avoid breaking other tests."""
100
118
settings.MIDDLEWARE_CLASSES = self.curr_middleware
Original file line number Diff line number Diff line change
@@ -38,3 +38,12 @@ if a file with the uploaded name already exists.
38
38
underscore plus a random 7 character alphanumeric string (e.g. ``"_x3a1gho"``),
39
39
rather than iterating through an underscore followed by a number (e.g. ``"_1"``,
40
40
``"_2"``, etc.).
41
+
42
+
``RemoteUserMiddleware`` session hijacking
43
+
==========================================
44
+
45
+
When using the :class:`~django.contrib.auth.middleware.RemoteUserMiddleware`
46
+
and the ``RemoteUserBackend``, a change to the ``REMOTE_USER`` header between
47
+
requests without an intervening logout could result in the prior user's session
48
+
being co-opted by the subsequent user. The middleware now logs the user out on
49
+
a failed login attempt.
You can’t perform that action at this time.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4