Search code examples
djangoauthenticationdjango-viewsdjango-users

Authenticate users with both username and email


I have extendted the UserCreationForm with email and other fields, so that I could authenticate a user with both its username and email.

forms.py:

class UserCreationForm(UserCreationForm):

    class Meta:
        model = User
        fields = ('first_name', 'last_name', 'username', 'email',)

views.py:

def auth_view(request):
    username = request.POST.get('username','')
    password = request.POST.get('password','')
    user = auth.authenticate(username=username, password=password)

    if user is not None:
        auth.login(request, user)
        return HttpResponseRedirect('/')
    elif:
        user = auth.authenticate(email=username, password=password)
        if user is not None:
            auth.login(request, user)
            return HttpResponseRedirect('/')
    else:
        return HttpResponseRedirect('/accounts/invalid_login')

html:

<form action="/accounts/auth/" method="post">
    {%csrf_token%}

    <label for="name">Email or Username:</label>
    <input type="text" name="name" id="name" value="">
    <label for="password">Password:</label>
    <input type="password" name="password" id="password" value="">

    <input type="submit" value="LOGIN">
</form>

In the views I tried giving both the username and email as input from the form as name, and check to see if username and password authenticate. If not then check whether email and password authenticate. But its not working. How do I solve this problem? Please kindly help me. Thank you.


Solution

  • You need to create an authentication backend: here is mine:

    class EmailAuthBackend(ModelBackend):
        """
        Email Authentication Backend
    
        Allows a user to sign in using an email/password pair, then check
        a username/password pair if email failed
        """
    
        def authenticate(self, username=None, password=None):
            """ Authenticate a user based on email address as the user name. """
            try:
                user = User.objects.get(email=username)
                if user.check_password(password):
                    return user
            except User.DoesNotExist:
                try:
                    user = User.objects.get(username=username)
                    if user.check_password(password):
                        return user
                except User.DoesNotExist:
                    return None
    
        def get_user(self, user_id):
            """ Get a User object from the user_id. """
            try:
                return User.objects.get(pk=user_id)
            except User.DoesNotExist:
                return None
    

    Then in your settings:

    AUTHENTICATION_BACKENDS = ('MyApp.backends.EmailAuthBackend',)
    

    then create a custom view the uses the authenticate function.