If you are building a Django frontend for a legacy application chances are you will need to integrate your existing user database table(s) with the the Django authentication system (django.contrib.auth). In this tutorial we will look at writing our own authentication backend and plugging it into django.contrib.auth.
Getting Started
Authentication backends are pure python classes. Given a username and password, they are expected to validate them against an authentication source (such as a database) and return a User object. There is no requirement as to where the class is placed, however I always put it in the same directory as the application that handles registrations and logging in.
When a user logs in, Django will check the AUTHENTICATION_BACKENDS (tuple) setting and iterate through all backends until one returns true. The default authentication backend is django.contrib.auth.backends.ModelBackend.
Writing Our Backend
Our backend must have two methods: authenticate and get_user
authenticate takes two arguments – username and password. It is expected to return a User instance or None. The authenticate method should check the given username and password against the user table of the legacy application. If the credentials match, then create a new User instance, save it, and return it. If they don’t match then return None.
get_user takes one argument – user_id. It is expected to return a User object.
Example
Below is an auth backend I have written for a legacy application. The application had a different password encryption algorithm and no permissions structure.
authenticate first tests the username and password in the legacy database. If it is valid then it will check if a User instance exists in the Django authentication system. If there is no record of the user in the Django User table, then we create a new user.
from account.models import Account from account.utils import trinity_password from django.contrib.auth.models import User class AuthBackend(object): def authenticate(self, username, password): try: account = Account.objects.using('realmd').get(username=username, sha_pass_hash=trinity_password(username, password)) try: user = User.objects.get(username=username) except User.DoesNotExist: user = User(username=account.username) user.is_staff = False user.is_superuser = False user.set_unusable_password() user.save() return user except Account.DoesNotExist: return None def get_user(self, id): try: return User.objects.get(id=id) except User.DoesNotExist: return None
To use our authentication backend we just need to add it to the AUTHENTICATION_BACKENDS tuple like so:
AUTHENTICATION_BACKENDS = ( 'pythonicPath.to.AuthBackend', ‘django.contrib.auth.backends.ModelBackend’, )
Conclusion
The Django authentication system is very flexible and allows you to easily write your own backend. If you have any questions about writing your own Django auth backend, or need any help doing so, feel free to comment below.