Creating a Custom Authentication Backend in Django
So you want to authenticate different types of users in different ways, or maybe you want to integrate your system with third-party authentication services like Firebase or Auth0, Whatever your use case maybe if you require a custom way of authenticating a user in Django then writing a custom authentication backend can be the right way to go.
What are Django authentication backends
An authentication backend is a class that implements two required methods:
get_user(user_id)
andauthenticate(request, **credentials)
as well as a set of optional permission related authorization methods.
If we take a look at part of the default authentication backend...
class ModelBackend(BaseBackend):
"""
Authenticates against settings.AUTH_USER_MODEL.
"""
def authenticate(self, request, username=None, password=None, **kwargs):
if username is None:
username = kwargs.get(UserModel.USERNAME_FIELD)
if username is None or password is None:
return
try:
user = UserModel._default_manager.get_by_natural_key(username)
except UserModel.DoesNotExist:
# Run the default password hasher once to reduce the timing
# difference between an existing and a nonexistent user (#20760).
UserModel().set_password(password)
else:
if user.check_password(password) and self.user_can_authenticate(user):
return user
def get_user(self, user_id):
try:
user = User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
return user if self.user_can_authenticate(user) else None
As you can see the authenticate method takes in a username
and a password
attribute and proceeds to authenticate the user, user_can_authenticate
checks if the user is active, After all checks have passed the user will be returned.
Note: The username
field is not necessarily the username
field in the User
model or the DB table but rather the USERNAME_FIELD variable you declare in your Model.
# The default authentication backend will use the email as username
USERNAME_FIELD = 'email'
So if you are just looking to authenticate all your users based on another field just use this setting.
I always find it quite nice to read Django's implementation to understand how it works and to understand how to better utilize it together with the documentation, blogs and tutorial videos, I advise all of you to do the same🙂, You can find Django's full authentication backend implementation here.
Implementing a custom authentication backend in only 2 steps🔥
Step 0: Spin up a new Django project
While I won't be showing you how to setup an environment, it's advised you use them when working on Python projects
django-admin startproject custom_auth
django-admin startapp auth
Step 1: Implementing the backend code
Hold up.. before you proceed to copy-paste the code😅, Create a "backends" folder and in it an AuthBackends.py
file. Now you can copy-paste!
class StaffIDAuthBackend(ModelBackend): #inherit from ModelBacken
def authenticate(self, request, staff_id=None, password=None, **kwargs):
if staff_id is None or password is None:
return
try:
user = User.objects.get(staff_id=staff_id)
except User.DoesNotExist:
# Run the default password hasher once to reduce the timing
# difference between an existing and a nonexistent user (#20760).
User().set_password(password)
else:
if user.check_password(password) and self.user_can_authenticate(user):
return user
def get_user(self, user_id):
try:
user = User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
return user if self.user_can_authenticate(user) else None
We have created an authentication backend for letting staff members log in to our system via their unique staff_id
.
Note: The field you choose to authenticate your user against needs to be unique or you need to pair it with another field that is in conjunction unique when used together with the staff_id
field.
Step 2: Telling Django we want to use our backend
In Django, when you want to use a custom backend for authentication, you need to configure it in your project's settings. We need to declare it in the AUTHENTICATION_BACKENDS
variable.
You won't need to import the class into the settings.py file rather you declare an absolute path starting from the app.
AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.ModelBackend',
'Users.backends.AuthBackends.StaffIDAuthBackend',
# format: app.go.through.the.folders.file.Class
]
Now Django will use the Auth backend automatically!
It's worth noting that during authentication Django goes through the list from top to bottom trying to authenticate against each backend until one works or all fail before the process fails altogether so order your auth model backends according to your specifications.
Conclusion
In this blog post, we have gone through the process of creating a custom Django authentication backend and also took a pick at how Django implements its auth backend, I hope you gained a little knowledge from this blog post, Cheers🤗
Subscribe to my newsletter
Read articles from Kaleb abebe directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Kaleb abebe
Kaleb abebe
I'm a passionate Fullstack developer based in Ethiopia, With a diverse skill set that includes JavaScript, TypeScript, React.js, Next.js, Python, Django and Django Rest Framework.