========================================= How to authenticate using ``REMOTE_USER`` ========================================= This document describes how to make use of external authentication sources (where the web server sets the ``REMOTE_USER`` environment variable) in your Django applications. This type of authentication solution is typically seen on intranet sites, with single sign-on solutions such as IIS and Integrated Windows Authentication or Apache and `mod_authnz_ldap`_, `CAS`_, `WebAuth`_, `mod_auth_sspi`_, etc. .. _mod_authnz_ldap: https://httpd.apache.org/docs/current/mod/mod_authnz_ldap.html .. _CAS: https://www.apereo.org/projects/cas .. _WebAuth: https://uit.stanford.edu/service/authentication .. _mod_auth_sspi: https://sourceforge.net/projects/mod-auth-sspi When the web server takes care of authentication it typically sets the ``REMOTE_USER`` environment variable for use in the underlying application. In Django, ``REMOTE_USER`` is made available in the :attr:`request.META ` attribute. Django can be configured to make use of the ``REMOTE_USER`` value using the ``RemoteUserMiddleware`` or ``PersistentRemoteUserMiddleware``, and :class:`~django.contrib.auth.backends.RemoteUserBackend` classes found in :mod:`django.contrib.auth`. Configuration ============= First, you must add the :class:`django.contrib.auth.middleware.RemoteUserMiddleware` to the :setting:`MIDDLEWARE` setting **after** the :class:`django.contrib.auth.middleware.AuthenticationMiddleware`:: MIDDLEWARE = [ "...", "django.contrib.auth.middleware.AuthenticationMiddleware", "django.contrib.auth.middleware.RemoteUserMiddleware", "...", ] Next, you must replace the :class:`~django.contrib.auth.backends.ModelBackend` with :class:`~django.contrib.auth.backends.RemoteUserBackend` in the :setting:`AUTHENTICATION_BACKENDS` setting:: AUTHENTICATION_BACKENDS = [ "django.contrib.auth.backends.RemoteUserBackend", ] With this setup, ``RemoteUserMiddleware`` will detect the username in ``request.META['REMOTE_USER']`` and will authenticate and auto-login that user using the :class:`~django.contrib.auth.backends.RemoteUserBackend`. Be aware that this particular setup disables authentication with the default ``ModelBackend``. This means that if the ``REMOTE_USER`` value is not set then the user is unable to log in, even using Django's admin interface. Adding ``'django.contrib.auth.backends.ModelBackend'`` to the ``AUTHENTICATION_BACKENDS`` list will use ``ModelBackend`` as a fallback if ``REMOTE_USER`` is absent, which will solve these issues. Django's user management, such as the views in ``contrib.admin`` and the :djadmin:`createsuperuser` management command, doesn't integrate with remote users. These interfaces work with users stored in the database regardless of ``AUTHENTICATION_BACKENDS``. .. note:: Since the ``RemoteUserBackend`` inherits from ``ModelBackend``, you will still have all of the same permissions checking that is implemented in ``ModelBackend``. Users with :attr:`is_active=False ` won't be allowed to authenticate. Use :class:`~django.contrib.auth.backends.AllowAllUsersRemoteUserBackend` if you want to allow them to. If your authentication mechanism uses a custom HTTP header and not ``REMOTE_USER``, you can subclass ``RemoteUserMiddleware`` and set the ``header`` attribute to the desired ``request.META`` key. For example:: from django.contrib.auth.middleware import RemoteUserMiddleware class CustomHeaderMiddleware(RemoteUserMiddleware): header = "HTTP_AUTHUSER" .. warning:: Be very careful if using a ``RemoteUserMiddleware`` subclass with a custom HTTP header. You must be sure that your front-end web server always sets or strips that header based on the appropriate authentication checks, never permitting an end-user to submit a fake (or "spoofed") header value. Since the HTTP headers ``X-Auth-User`` and ``X-Auth_User`` (for example) both normalize to the ``HTTP_X_AUTH_USER`` key in ``request.META``, you must also check that your web server doesn't allow a spoofed header using underscores in place of dashes. This warning doesn't apply to ``RemoteUserMiddleware`` in its default configuration with ``header = 'REMOTE_USER'``, since a key that doesn't start with ``HTTP_`` in ``request.META`` can only be set by your WSGI server, not directly from an HTTP request header. If you need more control, you can create your own authentication backend that inherits from :class:`~django.contrib.auth.backends.RemoteUserBackend` and override one or more of its attributes and methods. .. _persistent-remote-user-middleware-howto: Using ``REMOTE_USER`` on login pages only ========================================= The ``RemoteUserMiddleware`` authentication middleware assumes that the HTTP request header ``REMOTE_USER`` is present with all authenticated requests. That might be expected and practical when Basic HTTP Auth with ``htpasswd`` or similar mechanisms are used, but with Negotiate (GSSAPI/Kerberos) or other resource intensive authentication methods, the authentication in the front-end HTTP server is usually only set up for one or a few login URLs, and after successful authentication, the application is supposed to maintain the authenticated session itself. :class:`~django.contrib.auth.middleware.PersistentRemoteUserMiddleware` provides support for this use case. It will maintain the authenticated session until explicit logout by the user. The class can be used as a drop-in replacement of :class:`~django.contrib.auth.middleware.RemoteUserMiddleware` in the documentation above.