Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

django have the ability to login with phone or email

Tags:

django

I want to create a django custom user model such that i can have my users login with either phone or email.

This is my proposed solution

class ExtendedUser(AbstractBaseUser, PermissionsMixin):
    phonenumber = PhoneNumberField(unique=True, null=True ..)
    email = EmailField(unique=True, null=True ..)
    ...
    USERNAME_FIELD = 'pk'

so now while login, i can do something like this

if cleaned_data['phonenumber']:
   u = User.objects.get(phonenumber=cleaned_data['phonenumber'])
   authenticate(username=u.pk, password=cleaned_data['password'])
   ...

elif cleaned_data['email']:
   ...

I am not sure whether it is possible to put USERNAME_FIELD as pk. We can easily put a UUIDField if that's not possible.

Is the proposed solution fine?

like image 573
Dev Aggarwal Avatar asked Jan 17 '18 14:01

Dev Aggarwal


People also ask

How do I login as user in Django?

Django by default will look within a templates folder called registration for auth templates. The login template is called login. html . Create a new directory called templates and within it another directory called registration .

How does Django handle user authentication?

The Django authentication system handles both authentication and authorization. Briefly, authentication verifies a user is who they claim to be, and authorization determines what an authenticated user is allowed to do. Here the term authentication is used to refer to both tasks.

How do I authenticate using email and password in Django?

Email authentication for Django 3.x For using email/username and password for authentication instead of the default username and password authentication, we need to override two methods of ModelBackend class: authenticate() and get_user():


1 Answers

The unique constrain for Email and Phone are good. Also, I would set USERNAME_FIELD = 'email'.

Then, I think you should try to create a custom authentication backend. You can check here

Like Django says: When somebody calls django.contrib.auth.authenticate(), Django tries authenticating across all of its authentication backends.

Then in your custom authentication backend you can ask for Email or Phone:

class CustomAuthenticationBackend:

    def authenticate(self, request, email_or_phone=None, password=None):
        try:
             user = User.objects.get(
                 Q(email=email_or_phone) | Q(phone=email_or_phone)
             )
             pwd_valid = user.check_password(password)
             if pwd_valid:            
                 return user
             return None
        except User.DoesNotExist:
            return None

    def get_user(self, user_id):
        try:
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None

I think it can work. Let me know!!

Best regards.

like image 168
Marcos Schroh Avatar answered Sep 30 '22 15:09

Marcos Schroh