1. =========================================
    
  2. How to authenticate using ``REMOTE_USER``
    
  3. =========================================
    
  4. 
    
  5. This document describes how to make use of external authentication sources
    
  6. (where the web server sets the ``REMOTE_USER`` environment variable) in your
    
  7. Django applications.  This type of authentication solution is typically seen on
    
  8. intranet sites, with single sign-on solutions such as IIS and Integrated
    
  9. Windows Authentication or Apache and `mod_authnz_ldap`_, `CAS`_, `Cosign`_,
    
  10. `WebAuth`_, `mod_auth_sspi`_, etc.
    
  11. 
    
  12. .. _mod_authnz_ldap: https://httpd.apache.org/docs/2.2/mod/mod_authnz_ldap.html
    
  13. .. _CAS: https://www.apereo.org/projects/cas
    
  14. .. _Cosign: http://weblogin.org
    
  15. .. _WebAuth: https://uit.stanford.edu/service/authentication
    
  16. .. _mod_auth_sspi: https://sourceforge.net/projects/mod-auth-sspi
    
  17. 
    
  18. When the web server takes care of authentication it typically sets the
    
  19. ``REMOTE_USER`` environment variable for use in the underlying application.  In
    
  20. Django, ``REMOTE_USER`` is made available in the :attr:`request.META
    
  21. <django.http.HttpRequest.META>` attribute.  Django can be configured to make
    
  22. use of the ``REMOTE_USER`` value using the ``RemoteUserMiddleware``
    
  23. or ``PersistentRemoteUserMiddleware``, and
    
  24. :class:`~django.contrib.auth.backends.RemoteUserBackend` classes found in
    
  25. :mod:`django.contrib.auth`.
    
  26. 
    
  27. Configuration
    
  28. =============
    
  29. 
    
  30. First, you must add the
    
  31. :class:`django.contrib.auth.middleware.RemoteUserMiddleware` to the
    
  32. :setting:`MIDDLEWARE` setting **after** the
    
  33. :class:`django.contrib.auth.middleware.AuthenticationMiddleware`::
    
  34. 
    
  35.     MIDDLEWARE = [
    
  36.         '...',
    
  37.         'django.contrib.auth.middleware.AuthenticationMiddleware',
    
  38.         'django.contrib.auth.middleware.RemoteUserMiddleware',
    
  39.         '...',
    
  40.     ]
    
  41. 
    
  42. Next, you must replace the :class:`~django.contrib.auth.backends.ModelBackend`
    
  43. with :class:`~django.contrib.auth.backends.RemoteUserBackend` in the
    
  44. :setting:`AUTHENTICATION_BACKENDS` setting::
    
  45. 
    
  46.     AUTHENTICATION_BACKENDS = [
    
  47.         'django.contrib.auth.backends.RemoteUserBackend',
    
  48.     ]
    
  49. 
    
  50. With this setup, ``RemoteUserMiddleware`` will detect the username in
    
  51. ``request.META['REMOTE_USER']`` and will authenticate and auto-login that user
    
  52. using the :class:`~django.contrib.auth.backends.RemoteUserBackend`.
    
  53. 
    
  54. Be aware that this particular setup disables authentication with the default
    
  55. ``ModelBackend``. This means that if the ``REMOTE_USER`` value is not set
    
  56. then the user is unable to log in, even using Django's admin interface.
    
  57. Adding ``'django.contrib.auth.backends.ModelBackend'`` to the
    
  58. ``AUTHENTICATION_BACKENDS`` list will use ``ModelBackend`` as a fallback
    
  59. if ``REMOTE_USER`` is absent, which will solve these issues.
    
  60. 
    
  61. Django's user management, such as the views in ``contrib.admin`` and
    
  62. the :djadmin:`createsuperuser` management command, doesn't integrate with
    
  63. remote users. These interfaces work with users stored in the database
    
  64. regardless of ``AUTHENTICATION_BACKENDS``.
    
  65. 
    
  66. .. note::
    
  67. 
    
  68.     Since the ``RemoteUserBackend`` inherits from ``ModelBackend``, you will
    
  69.     still have all of the same permissions checking that is implemented in
    
  70.     ``ModelBackend``.
    
  71. 
    
  72.     Users with :attr:`is_active=False
    
  73.     <django.contrib.auth.models.User.is_active>` won't be allowed to
    
  74.     authenticate. Use
    
  75.     :class:`~django.contrib.auth.backends.AllowAllUsersRemoteUserBackend` if
    
  76.     you want to allow them to.
    
  77. 
    
  78. If your authentication mechanism uses a custom HTTP header and not
    
  79. ``REMOTE_USER``, you can subclass ``RemoteUserMiddleware`` and set the
    
  80. ``header`` attribute to the desired ``request.META`` key.  For example::
    
  81. 
    
  82.     from django.contrib.auth.middleware import RemoteUserMiddleware
    
  83. 
    
  84.     class CustomHeaderMiddleware(RemoteUserMiddleware):
    
  85.         header = 'HTTP_AUTHUSER'
    
  86. 
    
  87. .. warning::
    
  88. 
    
  89.     Be very careful if using a ``RemoteUserMiddleware`` subclass with a custom
    
  90.     HTTP header. You must be sure that your front-end web server always sets or
    
  91.     strips that header based on the appropriate authentication checks, never
    
  92.     permitting an end-user to submit a fake (or "spoofed") header value. Since
    
  93.     the HTTP headers ``X-Auth-User`` and ``X-Auth_User`` (for example) both
    
  94.     normalize to the ``HTTP_X_AUTH_USER`` key in ``request.META``, you must
    
  95.     also check that your web server doesn't allow a spoofed header using
    
  96.     underscores in place of dashes.
    
  97. 
    
  98.     This warning doesn't apply to ``RemoteUserMiddleware`` in its default
    
  99.     configuration with ``header = 'REMOTE_USER'``, since a key that doesn't
    
  100.     start with ``HTTP_`` in ``request.META`` can only be set by your WSGI
    
  101.     server, not directly from an HTTP request header.
    
  102. 
    
  103. If you need more control, you can create your own authentication backend
    
  104. that inherits from :class:`~django.contrib.auth.backends.RemoteUserBackend` and
    
  105. override one or more of its attributes and methods.
    
  106. 
    
  107. .. _persistent-remote-user-middleware-howto:
    
  108. 
    
  109. Using ``REMOTE_USER`` on login pages only
    
  110. =========================================
    
  111. 
    
  112. The ``RemoteUserMiddleware`` authentication middleware assumes that the HTTP
    
  113. request header ``REMOTE_USER`` is present with all authenticated requests. That
    
  114. might be expected and practical when Basic HTTP Auth with ``htpasswd`` or
    
  115. similar mechanisms are used, but with Negotiate (GSSAPI/Kerberos) or other
    
  116. resource intensive authentication methods, the authentication in the front-end
    
  117. HTTP server is usually only set up for one or a few login URLs, and after
    
  118. successful authentication, the application is supposed to maintain the
    
  119. authenticated session itself.
    
  120. 
    
  121. :class:`~django.contrib.auth.middleware.PersistentRemoteUserMiddleware`
    
  122. provides support for this use case. It will maintain the authenticated session
    
  123. until explicit logout by the user. The class can be used as a drop-in
    
  124. replacement of :class:`~django.contrib.auth.middleware.RemoteUserMiddleware`
    
  125. in the documentation above.