I would like to create an authentication backend that allows users to log_in only using their email (no username, no password).
Here is what I tried.
backends.py:
from django.conf import settings
from django.contrib.auth.models import User
class EmailAuthBackend(object):
def authenticate(self, username=None, password=None):
try:
user = User.objects.get(email=username)
if user:
return user
except User.DoesNotExist:
return None
settings.py:
AUTHENTICATION_BACKENDS = (
'path_to.backends.EmailAuthBackend',
'django.contrib.auth.backends.ModelBackend',
)
html:
<form method="post" action="{% url myproject.views.test %}">
{% csrf_token %}
<input type="text" name="email" value=""/>
<button type="submit">Valider</button>
</form>
view:
def test(request):
email = ''
if 'email' in request.POST:
email = request.POST.get('email')
if not User.objects.filter(email=email):
User.objects.create(email=email)
user = authenticate(username=email)
if user is not None:
if user.is_active:
auth_login(request, user)
return HttpResponseRedirect(reverse('home'))
It doesn't work, the user is not authenticated. And I also have this error when I go to the /admin:
AttributeError at /admin/logout/
'EmailAuthBackend' object has no attribute 'get_user'
To implement a custom authentication backend, you need to define a python class with two(2) methods. One for retrieving a user and the other for authenticating a user. The two methods are, get_user() and authenticate() respectively.
Authentication backends provide an extensible system for when a username and password stored with the user model need to be authenticated against a different service than Django's default. You can give your models custom permissions that can be checked through Django's authorization system.
For each custom backend in Django, you need to specify the get_user
function. See the documentation. The get_user
implementation can simply use the existing User table, like you are:
def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
The reason this is required is for situations where you'd need to fetch the User via its primary key from a different source.
While Bartek's answer is the correct one I'll just provide an example of another way to solve the problem by inheriting the ModelBackend
.
from django.contrib.auth.backends import ModelBackend
class EmailAuthBackend(ModelBackend):
def authenticate(self, username=None, password=None, **kwargs):
try:
user = User.objects.get(email=username)
if user.check_password(password):
return user
except ObjectDoesNotExist:
# Run the default password hasher once to reduce the timing
# difference between an existing and a non-existing user (#20760).
User().set_password(password)
The get_user
is already implemented by the ModelBackend
and you get the permission methods along with it.
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