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.
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 ...
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.”
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.
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
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',
]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With