Skip to content

Custom Authentication Backends

Django allows you to authenticate against different sources, such as LDAP directories or custom OAuth providers, by creating a custom authentication backend. You can use multiple backends simultaneously; Django will check them in the order they are defined.

Writing a Custom Backend

An authentication backend is a class that implements two methods: authenticate() and get_user(). If you are extending the default behavior (like allowing email login), you can subclass ModelBackend.

python
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth import get_user_model

User = get_user_model()

class EmailAuthBackend(ModelBackend):
    """
    Authenticate using an e-mail address.
    """
    def authenticate(self, request, username=None, password=None, **kwargs):
        try:
            user = User.objects.get(email=username)
            if user.check_password(password):
                return user
        except User.DoesNotExist:
            return None
        return None

    def get_user(self, user_id):
        try:
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None
python
from django.contrib.auth.backends import BaseBackend
from django.contrib.auth.models import User

class LDAPBackend(BaseBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        # 1. Connect to LDAP server
        # 2. Verify username and password
        # 3. If valid, get or create the Django User object
        # ...
        if valid_ldap_login:
            user, created = User.objects.get_or_create(username=username)
            return user
        return None

    def get_user(self, user_id):
        try:
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None

NOTE

If a backend raises django.core.exceptions.PermissionDenied, the entire login process fails immediately, and Django won't check any subsequent backends.

Configuring Backends

To use your custom backend, add its dotted Python path to the AUTHENTICATION_BACKENDS setting in settings.py.

python
AUTHENTICATION_BACKENDS = [
    # Custom backend first
    "myapp.backends.EmailAuthBackend",
    
    # Keep the default backend as a fallback
    "django.contrib.auth.backends.ModelBackend",
]

Django will try to authenticate the user using each backend in the list sequentially until one succeeds. Once a user successfully logs in, Django stores the path of the specific backend that authenticated them in their session cookie. On subsequent requests, Django uses that specific backend's get_user() method to fetch the user object.

This per-session storage means your app can easily support multiple login methods concurrently without conflict (e.g., Alice logs in via Email and her session remembers the Email backend, while Bob logs in via Username and his session remembers the default Model backend).