Commit 9741912a authored by Preston Holmes's avatar Preston Holmes
Browse files

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.
parent 2b5f8482
Loading
Loading
Loading
Loading
+14 −3
Original line number Diff line number Diff line
from django.contrib import auth
from django.contrib.auth import load_backend
from django.contrib.auth.backends import RemoteUserBackend
from django.core.exceptions import ImproperlyConfigured
from django.utils.functional import SimpleLazyObject

@@ -47,9 +49,18 @@ class RemoteUserMiddleware(object):
        try:
            username = request.META[self.header]
        except KeyError:
            # If specified header doesn't exist then return (leaving
            # request.user set to AnonymousUser by the
            # AuthenticationMiddleware).
            # If specified header doesn't exist then remove any existing
            # 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 ImproperlyConfigured as e:
                    # backend failed to load
                    auth.logout(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
+23 −2
Original line number Diff line number Diff line
from datetime import datetime

from django.conf import settings
from django.contrib.auth import authenticate
from django.contrib.auth.backends import RemoteUserBackend
from django.contrib.auth.models import User
from django.contrib.auth.models import User, AnonymousUser
from django.contrib.auth.tests.utils import skipIfCustomUser
from django.test import TestCase
from django.utils import timezone
@@ -23,7 +24,7 @@ class RemoteUserTest(TestCase):
        self.curr_middleware = settings.MIDDLEWARE_CLASSES
        self.curr_auth = settings.AUTHENTICATION_BACKENDS
        settings.MIDDLEWARE_CLASSES += (self.middleware,)
        settings.AUTHENTICATION_BACKENDS = (self.backend,)
        settings.AUTHENTICATION_BACKENDS += (self.backend,)

    def test_no_remote_user(self):
        """
@@ -97,6 +98,26 @@ class RemoteUserTest(TestCase):
        response = self.client.get('/remote_user/', REMOTE_USER=self.known_user)
        self.assertEqual(default_login, response.context['user'].last_login)

    def test_header_disappears(self):
        """
        Tests that a logged in user is logged out automatically when
        the REMOTE_USER header disappears during the same browser session.
        """
        User.objects.create(username='knownuser')
        # Known user authenticates
        response = self.client.get('/remote_user/', REMOTE_USER=self.known_user)
        self.assertEqual(response.context['user'].username, 'knownuser')
        # During the session, the REMOTE_USER header disappears. Should trigger logout.
        response = self.client.get('/remote_user/')
        self.assertEqual(response.context['user'].is_anonymous(), True)
        # verify the remoteuser middleware will not remove a user
        # authenticated via another backend
        User.objects.create_user(username='modeluser', password='foo')
        self.client.login(username='modeluser', password='foo')
        authenticate(username='modeluser', password='foo')
        response = self.client.get('/remote_user/')
        self.assertEqual(response.context['user'].username, 'modeluser')

    def tearDown(self):
        """Restores settings to avoid breaking other tests."""
        settings.MIDDLEWARE_CLASSES = self.curr_middleware
+3 −0
Original line number Diff line number Diff line
@@ -296,6 +296,9 @@ Django 1.5 also includes several smaller improvements worth noting:
  you to test equality for XML content at a semantic level, without caring for
  syntax differences (spaces, attribute order, etc.).

* RemoteUserMiddleware now forces logout when the REMOTE_USER header
  disappears during the same browser session.

Backwards incompatible changes in 1.5
=====================================