==============================================================
How to authenticate against Django's user database from Apache
==============================================================

Since keeping multiple authentication databases in sync is a common problem
when dealing with Apache, you can configure Apache to authenticate against
Django's :doc:`authentication system </topics/auth/index>` directly. This
requires Apache version >= 2.2 and mod_wsgi >= 2.0. For example, you could:

* Serve static/media files directly from Apache only to authenticated users.

* Authenticate access to a Subversion_ repository against Django users with
  a certain permission.

* Allow certain users to connect to a WebDAV share created with mod_dav_.

.. note::
    If you have installed a :ref:`custom user model <auth-custom-user>` and
    want to use this default auth handler, it must support an ``is_active``
    attribute. If you want to use group based authorization, your custom user
    must have a relation named 'groups', referring to a related object that has
    a 'name' field. You can also specify your own custom mod_wsgi
    auth handler if your custom cannot conform to these requirements.

.. _Subversion: https://subversion.apache.org/
.. _mod_dav: https://httpd.apache.org/docs/2.2/mod/mod_dav.html

Authentication with ``mod_wsgi``
================================

.. note::

    The use of ``WSGIApplicationGroup %{GLOBAL}`` in the configurations below
    presumes that your Apache instance is running only one Django application.
    If you are running more than one Django application, please refer to the
    `Defining Application Groups`_ section of the mod_wsgi docs for more
    information about this setting.

Make sure that mod_wsgi is installed and activated and that you have
followed the steps to set up :doc:`Apache with mod_wsgi
</howto/deployment/wsgi/modwsgi>`.

Next, edit your Apache configuration to add a location that you want
only authenticated users to be able to view:

.. code-block:: apache

    WSGIScriptAlias / /path/to/mysite.com/mysite/wsgi.py
    WSGIPythonPath /path/to/mysite.com

    WSGIProcessGroup %{GLOBAL}
    WSGIApplicationGroup %{GLOBAL}

    <Location "/secret">
        AuthType Basic
        AuthName "Top Secret"
        Require valid-user
        AuthBasicProvider wsgi
        WSGIAuthUserScript /path/to/mysite.com/mysite/wsgi.py
    </Location>

The ``WSGIAuthUserScript`` directive tells mod_wsgi to execute the
``check_password`` function in specified wsgi script, passing the user name and
password that it receives from the prompt. In this example, the
``WSGIAuthUserScript`` is the same as the ``WSGIScriptAlias`` that defines your
application :doc:`that is created by django-admin startproject
</howto/deployment/wsgi/index>`.

.. admonition:: Using Apache 2.2 with authentication

    Make sure that ``mod_auth_basic`` and ``mod_authz_user`` are loaded.

    These might be compiled statically into Apache, or you might need to use
    LoadModule to load them dynamically in your ``httpd.conf``:

    .. code-block:: apache

        LoadModule auth_basic_module modules/mod_auth_basic.so
        LoadModule authz_user_module modules/mod_authz_user.so

Finally, edit your WSGI script ``mysite.wsgi`` to tie Apache's authentication
to your site's authentication mechanisms by importing the ``check_password``
function::

    import os

    os.environ["DJANGO_SETTINGS_MODULE"] = "mysite.settings"

    from django.contrib.auth.handlers.modwsgi import check_password

    from django.core.handlers.wsgi import WSGIHandler

    application = WSGIHandler()


Requests beginning with ``/secret/`` will now require a user to authenticate.

The mod_wsgi `access control mechanisms documentation`_ provides additional
details and information about alternative methods of authentication.

.. _Defining Application Groups: https://modwsgi.readthedocs.io/en/develop/user-guides/configuration-guidelines.html#defining-application-groups
.. _access control mechanisms documentation: https://modwsgi.readthedocs.io/en/develop/user-guides/access-control-mechanisms.html

Authorization with ``mod_wsgi`` and Django groups
-------------------------------------------------

mod_wsgi also provides functionality to restrict a particular location to
members of a group.

In this case, the Apache configuration should look like this:

.. code-block:: apache

    WSGIScriptAlias / /path/to/mysite.com/mysite/wsgi.py

    WSGIProcessGroup %{GLOBAL}
    WSGIApplicationGroup %{GLOBAL}

    <Location "/secret">
        AuthType Basic
        AuthName "Top Secret"
        AuthBasicProvider wsgi
        WSGIAuthUserScript /path/to/mysite.com/mysite/wsgi.py
        WSGIAuthGroupScript /path/to/mysite.com/mysite/wsgi.py
        Require group secret-agents
        Require valid-user
    </Location>

To support the ``WSGIAuthGroupScript`` directive, the same WSGI script
``mysite.wsgi`` must also import the ``groups_for_user`` function which
returns a list groups the given user belongs to.

.. code-block:: python

    from django.contrib.auth.handlers.modwsgi import check_password, groups_for_user

Requests for ``/secret/`` will now also require user to be a member of the
"secret-agents" group.
