[Fixed]-Django custom authentication back-end doesn't work

34👍

Ok, I have tried this before with Django 2.0.5, but it stopped working with Django 2.1. I researched here and found that custom authentication backend class now expects parameter request in method authenticate. So the final code for Django 2.1 is:

class EmailBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwars):
        UserModel = get_user_model()
        try:
            user = UserModel.objects.get(email=username)
        except UserModel.DoesNotExist:
            return None
        else:
            if user.check_password(password):
                return user

        return None

5👍

Working in Django 3.x

Custom Authentication file would look like:

from django.contrib.auth import get_user_model


User = get_user_model()


class EmailAuthBackend(object):
    """It provides the functionality to slide down to email to login,
    instead of just username"""
    def authenticate(self,request,username=None,password=None):
        try:
            user = User.objects.get(email=username)
            if user.check_password(password):   #you can also test user.is_active
                return user 
            return None
        except User.DoesNotExist:
            return None

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

and in the settings.py we need to put:

#Custom Authentication Backend
AUTHENTICATION_BACKENDS = [
    'django.contrib.auth.backends.ModelBackend',
    'path_to_custom_backend.EmailAuthBackend',
]

1👍

I suppose this might help you.
Inheriting from a helper class and making a Custom user is a better approach rather than writing your own custom back end.

1👍

Django 2.1 – 4.0

When creating an authentication backend it is best to follow the example of ModelBackend and run the default password hasher.

The following backend will authenticate using emails as well as usernames.

# backends.py
from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend
from django.db.models import Q

UserModel = get_user_model()


class CustomModelBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        if username is None:
            username = kwargs.get(UserModel.USERNAME_FIELD, kwargs.get(UserModel.EMAIL_FIELD))
        if username is None or password is None:
            return
        try:
            user = UserModel._default_manager.get(
                Q(username__exact=username) | Q(email__iexact=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

Be sure to add your backend to settings.py

# settings.py

AUTHENTICATION_BACKENDS = ["path.to.backends.CustomModelBackend"]
👤bob

Leave a comment