Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #17869 - force logout when REMOTE_USER header disappears

If the current sessions user was logged in via a remote user backend log out
the user if REMOTE_USER header not available - otherwise leave it to other auth
middleware to install the AnonymousUser.

Thanks to Sylvain Bouchard for the initial patch and ticket maintenance.
  • Loading branch information...
commit 9741912a9aaad083eaa8b9780cde37e1843cc4ae 1 parent 2b5f848
Preston Holmes authored September 09, 2012
17  django/contrib/auth/middleware.py
... ...
@@ -1,4 +1,6 @@
1 1
 from django.contrib import auth
  2
+from django.contrib.auth import load_backend
  3
+from django.contrib.auth.backends import RemoteUserBackend
2 4
 from django.core.exceptions import ImproperlyConfigured
3 5
 from django.utils.functional import SimpleLazyObject
4 6
 
@@ -47,9 +49,18 @@ def process_request(self, request):
47 49
         try:
48 50
             username = request.META[self.header]
49 51
         except KeyError:
50  
-            # If specified header doesn't exist then return (leaving
51  
-            # request.user set to AnonymousUser by the
52  
-            # AuthenticationMiddleware).
  52
+            # If specified header doesn't exist then remove any existing
  53
+            # authenticated remote-user, or return (leaving request.user set to
  54
+            # AnonymousUser by the AuthenticationMiddleware).
  55
+            if request.user.is_authenticated():
  56
+                try:
  57
+                    stored_backend = load_backend(request.session.get(
  58
+                        auth.BACKEND_SESSION_KEY, ''))
  59
+                    if isinstance(stored_backend, RemoteUserBackend):
  60
+                        auth.logout(request)
  61
+                except ImproperlyConfigured as e:
  62
+                    # backend failed to load
  63
+                    auth.logout(request)
53 64
             return
54 65
         # If the user is already authenticated and that user is the user we are
55 66
         # getting passed in the headers, then the correct user is already
25  django/contrib/auth/tests/remote_user.py
... ...
@@ -1,8 +1,9 @@
1 1
 from datetime import datetime
2 2
 
3 3
 from django.conf import settings
  4
+from django.contrib.auth import authenticate
4 5
 from django.contrib.auth.backends import RemoteUserBackend
5  
-from django.contrib.auth.models import User
  6
+from django.contrib.auth.models import User, AnonymousUser
6 7
 from django.contrib.auth.tests.utils import skipIfCustomUser
7 8
 from django.test import TestCase
8 9
 from django.utils import timezone
@@ -23,7 +24,7 @@ def setUp(self):
23 24
         self.curr_middleware = settings.MIDDLEWARE_CLASSES
24 25
         self.curr_auth = settings.AUTHENTICATION_BACKENDS
25 26
         settings.MIDDLEWARE_CLASSES += (self.middleware,)
26  
-        settings.AUTHENTICATION_BACKENDS = (self.backend,)
  27
+        settings.AUTHENTICATION_BACKENDS += (self.backend,)
27 28
 
28 29
     def test_no_remote_user(self):
29 30
         """
@@ -97,6 +98,26 @@ def test_last_login(self):
97 98
         response = self.client.get('/remote_user/', REMOTE_USER=self.known_user)
98 99
         self.assertEqual(default_login, response.context['user'].last_login)
99 100
 
  101
+    def test_header_disappears(self):
  102
+        """
  103
+        Tests that a logged in user is logged out automatically when
  104
+        the REMOTE_USER header disappears during the same browser session.
  105
+        """
  106
+        User.objects.create(username='knownuser')
  107
+        # Known user authenticates
  108
+        response = self.client.get('/remote_user/', REMOTE_USER=self.known_user)
  109
+        self.assertEqual(response.context['user'].username, 'knownuser')
  110
+        # During the session, the REMOTE_USER header disappears. Should trigger logout.
  111
+        response = self.client.get('/remote_user/')
  112
+        self.assertEqual(response.context['user'].is_anonymous(), True)
  113
+        # verify the remoteuser middleware will not remove a user
  114
+        # authenticated via another backend
  115
+        User.objects.create_user(username='modeluser', password='foo')
  116
+        self.client.login(username='modeluser', password='foo')
  117
+        authenticate(username='modeluser', password='foo')
  118
+        response = self.client.get('/remote_user/')
  119
+        self.assertEqual(response.context['user'].username, 'modeluser')
  120
+
100 121
     def tearDown(self):
101 122
         """Restores settings to avoid breaking other tests."""
102 123
         settings.MIDDLEWARE_CLASSES = self.curr_middleware
3  docs/releases/1.5.txt
@@ -296,6 +296,9 @@ Django 1.5 also includes several smaller improvements worth noting:
296 296
   you to test equality for XML content at a semantic level, without caring for
297 297
   syntax differences (spaces, attribute order, etc.).
298 298
 
  299
+* RemoteUserMiddleware now forces logout when the REMOTE_USER header
  300
+  disappears during the same browser session.
  301
+
299 302
 Backwards incompatible changes in 1.5
300 303
 =====================================
301 304
 

0 notes on commit 9741912

Please sign in to comment.
Something went wrong with that request. Please try again.