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.
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 Nonefrom 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 NoneNOTE
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.
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).
