Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django custom authentication back-end doesn't work

Tags:

python

django

I want my Django project to authenticate users with their email instead of their user-name. I followed this suggestion, but it doesn't work.

This is my EmailBackend

from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend

class EmailBackend(ModelBackend):
    def authenticate(self, 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

I have added AUTHENTICATION_BACKENDS = ['GeneralApp.utils.EmailBackend'] to settings.py and, when it is commented, I can login using user-name, and when I uncomment it, I cannot login anymore. I have traced out that the code of GeneralApp.utils.EmailBackend.authenticate() is never executed, but I know Django can locate the class because I have misspelled it intentionally and I get an error, and when I correct the typo, no exception is raised. I also know that the default authentication backend was effectively override because I cannot neither login with user-name. I have this same solution working perfectly in another project so I cannot understand why the custom authentication code is never executed when the class is perfectly located with AUTHENTICATION_BACKENDS set to it.

like image 640
HuLu ViCa Avatar asked Aug 16 '18 06:08

HuLu ViCa


People also ask

How do I manually authenticate in Django?

from django.contrib.auth import authenticate, login def my_view(request): username = request.POST['username'] password = request.POST['password'] user = authenticate(request, username=username, password=password) if user is not None: login(request, user) # Redirect to a success page. ... else: # Return an 'invalid ...

Which method of authentication backend takes credentials in Django?

Using the authenticate function to process each credential as a keyword argument, you can verify users' credentials. It checks the credentials against the authentication backend and returns User objects if they are valid. If they are not valid for a backend or they have no permissions, Django will return “none.”

What is Auth_user_model?

AUTH_USER_MODEL is the recommended approach when referring to a user model in a models.py file. For this you need to create custom User Model by either subclassing AbstractUser or AbstractBaseUser.


2 Answers

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
like image 187
HuLu ViCa Avatar answered Oct 19 '22 19:10

HuLu ViCa


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',
]
like image 42
MbeforeL Avatar answered Oct 19 '22 18:10

MbeforeL