La autenticación en django funciona a través de dos middleware dependientes, `SessionMiddleware` y `AuthenticationMiddleware`. Básicamente, cuando el usuario hace un login exitoso, se guardan tres valores en la sesión:

- `_auth_user_id`. PK del objeto User

- `_auth_user_backend`._Dotted path_ del backend de autenticación. Por defecto: `django.contrib.auth.backends.ModelBackend`

- `_auth_user_hash`. Hash de la contraseña del usuario

El hash es la representación hexadecimal (string) de un hasheado con sal de la contraseña del usuario:

    #!python

    def get_session_auth_hash(self):

        """
        Return an HMAC of the password field.
        """

        key_salt = "django.contrib.auth.models.AbstractBaseUser.get_session_auth_hash"
        return salted_hmac(key_salt, self.password).hexdigest()

En todos los requests `AuthenticationMiddleware` es el encargado de establecer cuál es el usuario `request.user`. Para ello llama a la función get_user del módulo `django.contrib.auth` y lo que hace es comprobar que la contraseña hasheada guardada en la sesión es la misma que se deriva de hacer el mismo cálculo sobre la guardada en la base de datos. Para ello usa la función `constant_time_compare` del módulo `django.utils.crypto`. Se usa esta función para que el tiempo que tome la comparación sea constante y se minimice la posibilidad de un [timing attack](https://en.wikipedia.org/wiki/Timing_attack). Si la comparación no es correcta establece como valor de request.user `AnonymousUser`.
  

    #!python

    # django/contrib/auth/middleware.py

    def get_user(request):

        if not hasattr(request, '_cached_user'):
            request._cached_user = auth.get_user(request)
        return request._cached_user

    class AuthenticationMiddleware(MiddlewareMixin):

        def process_request(self, request):
            assert hasattr(request, 'session'), (
                "The Django authentication middleware requires session middleware "
                "to be installed. Edit your MIDDLEWARE%s setting to insert "
                "'django.contrib.sessions.middleware.SessionMiddleware' before "
                "'django.contrib.auth.middleware.AuthenticationMiddleware'."
            ) % ("_CLASSES" if settings.MIDDLEWARE is None else "")
            request.user = SimpleLazyObject(lambda: get_user(request))

Ver tb:

    #!python

    # django/contrib/auth/init.py

    def get_user(request):
        """
        Return the user model instance associated with the given request session.
        If no user is retrieved, return an instance of `AnonymousUser`.
        """
        from .models import AnonymousUser
        user = None
        try:
            user_id = _get_user_session_key(request)
            backend_path = request.session[BACKEND_SESSION_KEY]
        except KeyError:
            pass
        else:
            if backend_path in settings.AUTHENTICATION_BACKENDS:
                backend = load_backend(backend_path)
                user = backend.get_user(user_id)
                # Verify the session
                if hasattr(user, 'get_session_auth_hash'):
                    session_hash = request.session.get(HASH_SESSION_KEY)
                    session_hash_verified = session_hash and constant_time_compare(
                        session_hash,
                        user.get_session_auth_hash()
                    )
                    if not session_hash_verified:
                        request.session.flush()
                        user = None

        return user or AnonymousUser()