Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom authentication backend. Django

Tags:

django

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'
like image 513
Marcolac Avatar asked Dec 19 '12 14:12

Marcolac


People also ask

How do I create a custom authentication backend in Django?

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.

What is authentication backend in Django?

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.


2 Answers

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.

like image 175
Bartek Avatar answered Oct 31 '22 18:10

Bartek


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.

like image 7
Daniel Backman Avatar answered Oct 31 '22 19:10

Daniel Backman