diff -r 581e90af582f django/contrib/auth/backends.py
--- a/django/contrib/auth/backends.py	Sat Dec 01 23:22:19 2007 -0300
+++ b/django/contrib/auth/backends.py	Sun Dec 02 01:59:46 2007 -0300
@@ -1,11 +1,11 @@ from django.db import connection
 from django.db import connection
 from django.contrib.auth.models import User
 
-try: 
-    set 
-except NameError: 
+try:
+    set
+except NameError:
     from sets import Set as set # Python 2.3 fallback
- 	
+
 class ModelBackend:
     """
     Authenticate against django.contrib.auth.models.User
@@ -50,7 +50,7 @@ class ModelBackend:
             cursor.execute(sql, [user_obj.id])
             user_obj._group_perm_cache = set(["%s.%s" % (row[0], row[1]) for row in cursor.fetchall()])
         return user_obj._group_perm_cache
-    
+
     def get_all_permissions(self, user_obj):
         if not hasattr(user_obj, '_perm_cache'):
             user_obj._perm_cache = set([u"%s.%s" % (p.content_type.app_label, p.codename) for p in user_obj.user_permissions.select_related()])
@@ -68,3 +68,55 @@ class ModelBackend:
             return User.objects.get(pk=user_id)
         except User.DoesNotExist:
             return None
+
+class RemoteUserAuthBackend:
+
+    def __init__(self):
+        if self.__class__ == RemoteUserAuthBackend:
+            raise TypeError, "You must create your own class derived\
+from Remote UserAuthBackend in order to use it."
+
+    def authenticate(self, username, password=None):
+        """
+        Authenticate user - RemoteUserAuth middleware passes REMOTE_USER
+        as username.
+        """
+        if password is not None:
+            return None
+        user = None
+        if username:
+            username = self.parse_user(username)
+            try:
+                user = User.objects.get(username=username)
+            except User.DoesNotExist:
+                user = self.unknown_user(username)
+                user = self.configure_user(user)
+        return user
+
+    def parse_user(self, username):
+        """ Parse the provided username.
+        Override this method if you need to do special things with the
+        username, like stripping @realm or cleaning something like
+        cn=x,dc=sas,etc.
+        """
+        return username
+
+    def get_user(self, user_id):
+        try:
+            return User.objects.get(pk=user_id)
+        except User.DoesNotExist:
+            return None
+
+    def unknown_user(self, username):
+        # Auto-create user
+        user = User.objects.create_user(username, '')
+        user.is_staff = False
+        user.save()
+        return user
+
+    def configure_user(self, user):
+        """ Configure a user after login.
+        i.e: to read group membership from LDAP and so on.
+        """
+        return user
+
diff -r 581e90af582f django/contrib/auth/middleware.py
--- a/django/contrib/auth/middleware.py	Sat Dec 01 23:22:19 2007 -0300
+++ b/django/contrib/auth/middleware.py	Sun Dec 02 01:59:46 2007 -0300
@@ -10,3 +10,21 @@ class AuthenticationMiddleware(object):
         assert hasattr(request, 'session'), "The Django authentication middleware requires session middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert 'django.contrib.sessions.middleware.SessionMiddleware'."
         request.__class__.user = LazyUser()
         return None
+
+class RemoteUserAuthMiddleware(object):
+    def process_request(self, request):
+        from django.contrib.auth import authenticate, login
+        # AuthenticationMiddleware is required to create request.user
+        error = """The Django RemoteUserAuth middleware requires authentication middleware to be installed. Edit your MIDDLEWARE_CLASSES
+setting to insert 'django.contrib.auth.middleware.AuthenticationMiddleware' *before* the RemoteUserMiddleware class."""
+        assert hasattr(request, 'user'), error
+        if request.user.is_anonymous():
+            user = None
+            try:
+                user = authenticate(username=request.META['REMOTE_USER'])
+            except KeyError:
+                pass # No remote user available
+            if user is not None:
+                request.user = user    # set request.user to the authenticated user
+                login(request, user)   # auto-login the user to Django
+        return None
diff -r 581e90af582f django/contrib/auth/tests.py
--- a/django/contrib/auth/tests.py	Sat Dec 01 23:22:19 2007 -0300
+++ b/django/contrib/auth/tests.py	Sun Dec 02 01:59:46 2007 -0300
@@ -1,3 +1,51 @@
+import os
+import unittest
+from django.contrib.auth.models import User
+from django.contrib.auth.backends import RemoteUserAuthBackend
+from django.test.client import Client
+from django.conf import settings
+
+class SimpleDerivedBackend(RemoteUserAuthBackend):
+    pass
+
+class HttpAuthTest(unittest.TestCase):
+    def setUp(self):
+        self.extra_headers = {'REMOTE_USER': 'iamnotanuser'}
+        self.curr_middleware = settings.MIDDLEWARE_CLASSES
+        self.curr_auth = settings.AUTHENTICATION_BACKENDS
+
+        settings.MIDDLEWARE_CLASSES +=\
+            ('django.contrib.auth.middleware.RemoteUserAuthMiddleware', )
+        settings.AUTHENTICATION_BACKENDS =\
+            ('django.contrib.auth.tests.SimpleDerivedBackend',)
+
+    def testBackendMustBeDerived(self):
+        """
+        HttpAuthTest.testBackendMustBeDerived: RemoteUserAuthBackend cannot be
+        used without being inherited by another class.
+        """
+        # RemoteUserAuthBackend cannot be instantiated!
+        self.assertRaises(TypeError, RemoteUserAuthBackend)
+
+        # Check that it won't work on a request.
+        settings.AUTHENTICATION_BACKENDS =\
+            ('django.contrib.auth.backends.RemoteUserAuthBackend',)
+        c = Client()
+        self.assertRaises(TypeError, c.get ,'/', {}, **self.extra_headers)
+        
+    def testRemoteUserIsRespected(self):
+        c = Client()
+        extra_headers = {'REMOTE_USER': 'iamnotanuser'}
+        res = c.get('/', {}, **self.extra_headers)
+
+        u = User.objects.get(username='iamnotanuser')
+        # wow, the user was created! this works.
+
+    def tearDown(self):
+        # Restore settings to avoid breaking other tests.
+        settings.MIDDLEWARE_CLASSES = self.curr_middleware
+        settings.AUTHENTICATION_BACKENDS = self.curr_auth
+        
 """
 >>> from models import User, AnonymousUser
 >>> u = User.objects.create_user('testuser', 'test@example.com', 'testpw')
@@ -23,4 +71,4 @@ False
 []
 >>> a.user_permissions.all()
 []
-"""
\ No newline at end of file
+"""
diff -r 581e90af582f docs/auth_remote_user.txt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/auth_remote_user.txt	Sun Dec 02 01:59:46 2007 -0300
@@ -0,0 +1,70 @@
+======================================================
+Authenticating against REMOTE_USER from the Web Server
+======================================================
+
+Typically on intranet sites users are already authenticated (i.e. in a Windows
+domain) by the web server (i.e. using IIS Integrated Authentication).
+
+When the web server takes care of authentication it sets the ``REMOTE_USER`` HTTP
+header for use in the underlying application (i.e. Django). Then it's up to
+this application take care of the authorization.
+
+Django brings all you need to make use of the ``REMOTE_USER`` header bringing you
+one step furder to single sign-on on enterprise infrastucure!
+
+We assume that you have already configured your web server to authenticate
+users, maybe with mod_auth_sspi in Apache, Integrated Authentication in IIS
+and so on.
+
+Configuring Django
+==================
+
+First of all, you must add the ``RemoteUserAuthMiddleware`` just **after**
+(never before) ``AuthenticationMiddleware``.
+
+After this, you'll have to create you authentication backend that will take
+care of checking that ``REMOTE_USER`` is valid. But don't be scared,
+``RemoteUserAuthBackend`` is here to help you.
+
+``RemoteUserAuthBackend`` provides a "template" of what you need, you could
+create a backend that simply inherits it and you are done. It will simply
+assume that ``REMOTE_USER`` is always correct and create ``User``objects for
+it.
+
+If you want more control, in you inherited authentication backend you can
+override a few methods:
+
+   * ``parse_user``: Should cleanup ``REMOTE_USER`` (i.e. strip @realm from
+     it). It takes the ``username`` as argument, and must return the cleaned
+     ``username``.
+   * ``unkown_user``: Should create and return a ``User`` object, will be
+     called when a ``User`` object does not exist for ``REMOTE_USER``. Takes
+     ``username`` as it's only argument.
+   * ``configure_user``: Will be called after ``unkown_user`` so you can
+     configure the recently created ``User`` object (in case you did not want
+     to override ``unkown_user``. Takes the ``User`` instance as an argument.
+     Should also return the ``User`` instance that represents the User.
+
+
+Examples:
+
+    settings.py::
+
+        MIDDLEWARE_CLASSES = (
+            'django.contrib.auth.middleware.AuthenticationMiddleware',
+            'django.contrib.auth.middleware.RemoteUserAuthMiddleware',
+            ...
+            )
+            
+        AUTHENTICATION_BACKENDS = (
+            'myproject.backends.MyDerivedBackend',
+        )
+
+    myproject/backends.py::
+
+        from django.contrib.auth.backends import RemoteUserAuthBackend
+
+        class MyDerivedBackend(RemoteUserAuthBackend):
+            # We don't really do anything, we are fine with the default
+            # behaviour.
+            pass 
diff -r 581e90af582f docs/authentication.txt
--- a/docs/authentication.txt	Sat Dec 01 23:22:19 2007 -0300
+++ b/docs/authentication.txt	Sun Dec 02 01:59:46 2007 -0300
@@ -380,14 +380,14 @@ This example shows how you might use bot
             # Return an 'invalid login' error message.
 
 .. admonition:: Calling ``authenticate()`` first
-    
+
     When you're manually logging a user in, you *must* call
     ``authenticate()`` before you call ``login()``; ``authenticate()``
     sets an attribute on the ``User`` noting which authentication
     backend successfully authenticated that user (see the `backends
     documentation`_ for details), and this information is needed later
     during the login process.
-    
+
 .. _backends documentation: #other-authentication-sources
 
 Manually checking a user's password
@@ -460,7 +460,7 @@ introduced in Python 2.4::
 
 In the Django development version, ``login_required`` also takes an optional
 ``redirect_field_name`` parameter. Example::
-    
+
     from django.contrib.auth.decorators import login_required
 
     def my_view(request):
@@ -468,7 +468,7 @@ In the Django development version, ``log
     my_view = login_required(redirect_field_name='redirect_to')(my_view)
 
 Again, an equivalent example of the more compact decorator syntax introduced in Python 2.4::
-    
+
     from django.contrib.auth.decorators import login_required
 
     @login_required(redirect_field_name='redirect_to')
@@ -479,7 +479,7 @@ Again, an equivalent example of the more
 
     * If the user isn't logged in, redirect to ``settings.LOGIN_URL``
       (``/accounts/login/`` by default), passing the current absolute URL
-      in the query string as ``next`` or the value of ``redirect_field_name``. 
+      in the query string as ``next`` or the value of ``redirect_field_name``.
       For example:
       ``/accounts/login/?next=/polls/3/``.
     * If the user is logged in, execute the view normally. The view code is
@@ -1019,6 +1019,15 @@ database-based scheme, or you can use th
 database-based scheme, or you can use the default system in tandem with other
 systems.
 
+.. admonition:: Handling authentication at the web server
+
+    There's a very specific situation/scenario in which you want to handle
+    authentication at the web server's level (i.e. standard HTTP AUTH) and want
+    Django to honour this authentication. This is covered in a separate page:
+    `Authenticating against REMOTE_USER from the Web Server`_
+
+.. _Authenticating against REMOTE_USER from the Web Server: ../auth_remote_user/
+
 Specifying authentication backends
 ----------------------------------
 
@@ -1119,7 +1128,7 @@ Handling authorization in custom backend
 Handling authorization in custom backends
 -----------------------------------------
 
-Custom auth backends can provide their own permissions. 
+Custom auth backends can provide their own permissions.
 
 The user model will delegate permission lookup functions
 (``get_group_permissions()``, ``get_all_permissions()``, ``has_perm()``, and
@@ -1132,9 +1141,9 @@ one backend grants.
 
 The simple backend above could implement permissions for the magic admin fairly
 simply::
-        
+
     class SettingsBackend:
-    
+
         # ...
 
         def has_perm(self, user_obj, perm):
@@ -1142,7 +1151,7 @@ simply::
                 return True
             else:
                 return False
-                
+
 This gives full permissions to the user granted access in the above example. Notice
 that the backend auth functions all take the user object as an argument, and
 they also accept the same arguments given to the associated ``User`` functions.
diff -r 581e90af582f docs/request_response.txt
--- a/docs/request_response.txt	Sat Dec 01 23:22:19 2007 -0300
+++ b/docs/request_response.txt	Sun Dec 02 01:59:46 2007 -0300
@@ -109,6 +109,7 @@ All attributes except ``session`` should
         * ``QUERY_STRING`` -- The query string, as a single (unparsed) string.
         * ``REMOTE_ADDR`` -- The IP address of the client.
         * ``REMOTE_HOST`` -- The hostname of the client.
+        * ``REMOTE_USER`` -- The user authenticated by the web server, if any.
         * ``REQUEST_METHOD`` -- A string such as ``"GET"`` or ``"POST"``.
         * ``SERVER_NAME`` -- The hostname of the server.
         * ``SERVER_PORT`` -- The port of the server.
