djangodjango-rest-frameworkjwtdjango-rest-framework-jwt

DRF simple jwt getting auth token from a user instance OR change username and password combination


I have a chat app that uses the same authentication method as in WhatsApp.

Normally I would get the jwt auth token with this:

from rest_framework_simplejwt.views import TokenObtainView
path('api/token/', TokenObtainView.as_view(), name='token_obtain_pair'),

However This asks for both username and password while my user model is using phone_number and a validation code instead. Is there any way to change this?

username ======> phone_number password ======> phone_code (The validation code)

The second way Is to pass the user instance and get the auth token from it somehow

my Login view

@api_view(['POST',])
def loginuser(request):
    if request.method == 'POST':
        phone_number = request.data.get('phone_number')
        try:
            user = User.objects.get(phone_number=phone_number)
            if int(request.data.get('phone_code')) == user.phone_code and user.phone_code:
                # user.phone_code = None
                # user.save()
                return Response({'phone_number': phone_number}, status.HTTP_200_OK)

            else:
                return Response({'error': "Invalid code"}, status.HTTP_400_BAD_REQUEST)
        except Exception as error:
                return Response({'error': error}, status.HTTP_500_INTERNAL_SERVER_ERROR)

my user model:

class User(AbstractUser):
    phone_number = PhoneNumberField(unique=True)
    username = models.CharField(max_length=30)
    password = models.CharField(null=True, blank=True, max_length=20)
    about = models.CharField(
        max_length=190, default="Hi, I use Orgachat!", blank=True, null=True)
    ...
    phone_code = models.IntegerField(blank=True, null=True)    
    USERNAME_FIELD = 'phone_number'
    

    def __str__(self):
        return str(self.username)

# Save auth token, I know this should be in signals.py but whatever    
@receiver(post_save, sender=User)
def create_auth_token(sender, instance=None, created=False, **kwargs):
    if created:
        Token.objects.create(user=instance)

Solution

  • I think it's better to write your custom backend class and add it to Django this is intended to allow different ways to authenticate, see

    Also, you can inherit from TokenObtainView and add your logic there and use this custom class instead, but I prefer to integrate the first option with JWT so you need to read the docs and see how it works.

    I just realised that django-rest-framework-jwt tag is there, you should drop using this package as it's unmaintained, use django-rest-framework-simplejwt instead