Integrating with an Authentication System

It’s possible to integrate Django with an existing authentication system — another source of usernames and passwords or authentication methods. For example, your company may already have an LDAP setup that stores a username and password for every employee. It would be a hassle for both the network administrator and the users themselves if users had separate accounts in LDAP and the Django-based applications.

To handle situations like this, the Django authentication system lets you plug in other authentication sources. You can override Django’s default database-based scheme, or you can use
the default system in tandem with other systems.

Specifying Authentication Back-ends – Behind the scenes, Django maintains a list of “authentication back-ends” that it checks for authentication. When somebody calls django.contrib.auth.authenticate(), Django tries authenticating across all of its authentication back-ends. If the first authentication method fails, Django tries the second one, and so on, until all back-ends have been attempted.

The list of authentication back-ends to use is specified in the AUTHENTICATION_BACKENDS setting. This should be a tuple of Python path names that point to Python classes that know how to authenticate. These classes can be anywhere on your Python path. By default, AUTHENTICATION_BACKENDS is set to the following:

(‘django.contrib.auth.backends.ModelBackend’,)

That’s the basic authentication scheme that checks the Django users database. The order of AUTHENTICATION_BACKENDS matters, so if the same username and password are valid in multiple back-ends, Django will stop processing at the first positive match.

Writing an Authentication Back-end – An authentication back-end is a class that implements two methods: get_user(id) and authenticate(**credentials). The get_user method takes an id — which could be a username, database ID, or whatever — and returns a User object. The authenticate method takes credentials as keyword arguments. Most of the time it looks like this:

class MyBackend(object):
def authenticate(self, username=None, password=None):
# Check the username/password and return a User.

But it could also authenticate a token, like so:

class MyBackend(object):
def authenticate(self, token=None):
# Check the token and return a User.

Either way, authenticate should check the credentials it gets, and it should return a User object that matches those credentials, if the credentials are valid. If they’re not valid, it should return None. The Django admin system is tightly coupled to Django’s own database-backed User object. The best way to deal with this is to create a Django User object for each user that exists for your back-end (e.g., in your LDAP directory, your external SQL database, etc.). Either you can write a script to do this in advance or your authenticate method can do it the first time a user logs in.

Here’s an example back-end that authenticates against a username and password variable defined
in your settings.py file and creates a Django User object the first time a user authenticates:

from django.conf import settings
from django.contrib.auth.models import User, check_password
class SettingsBackend(object):
“””
Authenticate against the settings ADMIN_LOGIN and ADMIN_PASSWORD.
Use the login name, and a hash of the password. For example:
ADMIN_LOGIN = ‘admin’
ADMIN_PASSWORD = ‘sha1$4e987$afbcf42e21bd417fb71db8c66b321e9fc33051de’
“””
def authenticate(self, username=None, password=None):
login_valid = (settings.ADMIN_LOGIN == username)
pwd_valid = check_password(password, settings.ADMIN_PASSWORD)
if login_valid and pwd_valid:
try:
user = User.objects.get(username=username)
except User.DoesNotExist:
# Create a new user. Note that we can set password
# to anything, because it won’t be checked; the password
# from settings.py will.
user = User(username=username, password=’get from settings.py’)
user.is_staff = True
user.is_superuser = True
user.save()
return user
return None

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

Share this post
[social_warfare]
Integrating with a Legacy Database
Integrating with Legacy Web Applications

Get industry recognized certification – Contact us

keyboard_arrow_up