Building a custom authentication backend

Django allows you to authenticate against different sources. The AUTHENTICATION_BACKENDS setting includes the list of authentication backends for your project. By default, this setting is set to the following:

('django.contrib.auth.backends.ModelBackend',)

The default ModelBackend authenticates users against the database using the User model of django.contrib.auth. This will suit most of your projects. However, you can create custom backends to authenticate your user against other sources like a LDAP directory or any other system.

You can read more information about customizing authentication at https://docs.djangoproject.com/en/1.8/topics/auth/customizing/#other-authentication-sources.

Whenever you use the authenticate() function of django.contrib.auth, Django tries to authenticate the user against each of the backends defined in AUTHENTICATION_BACKENDS one by one, until one of them successfully authenticates the user. Only if all of the backends fail to authenticate the user, he or she will not be authenticated into your site.

Django provides a simple way to define your own authentication backends. An authentication backend is a class that provides the following two methods:

  • authenticate(): Takes user credentials as parameters. Has to return True if the user has been successfully authenticated, or False otherwise.
  • get_user(): Takes a user ID parameter and has to return a User object.

Creating a custom authentication backend is as simple as writing a Python class that implements both methods. We are going to create an authentication backend to let users authenticate in our site using their e-mail address instead of their username.

Create a new file inside your account application directory and name it authentication.py. Add the following code to it:

from django.contrib.auth.models import User

class EmailAuthBackend(object):
    """
    Authenticate using e-mail account.
    """
    def authenticate(self, username=None, password=None):
        try:
            user = User.objects.get(email=username)
            if user.check_password(password):
                return user
            return None
        except User.DoesNotExist:
            return None

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

This is a simple authentication backend. The authenticate() method receives the username and password optional parameters. We could use different parameters, but we use username and password to make our backend work with the authentication framework views straightaway. The preceding code works as follows:

  • authenticate(): We try to retrieve a user with the given e-mail address and check the password using the built-in check_password() method of the User model. This method handles the password hashing to compare the given password against the password stored in the database.
  • get_user(): We get a user by the ID set in the user_id parameter. Django uses the backend that authenticated the user to retrieve the User object for the duration of the user session.

Edit the settings.py file of your project and add the following setting:

AUTHENTICATION_BACKENDS = (
    'django.contrib.auth.backends.ModelBackend',
    'account.authentication.EmailAuthBackend',
)

We keep the default ModelBackend that is used to authenticate with username and password, and we include our own email-based authentication backend. Now, open http://127.0.0.1:8000/account/login/ in your browser. Remember that Django will try to authenticate the user against each of the backends, so now you should be able to log in using your username or e-mail account seamlessly.

Note

The order of the backends listed in the AUTHENTICATION_BACKENDS setting matters. If the same credentials are valid for multiple backends, Django will stop at the first backend that successfully authenticates the user.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset