17

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' 

2 Answers 2

22

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.

Sign up to request clarification or add additional context in comments.

Comments

7

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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.