0
votes

So I was trying to build a backend for my Android application. I was trying to apply a login procedure that works with JWT Token

This is what I have done :

  1. I have made a custom User model.
  2. Customize my superuser to take phone number and password, instead of username and password
  3. I have successfully created superuser and store it in my database (using postgreSQL).
  4. I have also customize my token claims and response as seen in my serializers.py of class LoginSerializer.

However, I encounter some problem after what I did :

  1. Right now, after customizing my user model, I was not able to login to Django administration with my new custom made User model, even though I have succesfully created a superuser.
  2. I still can't get the token even after I have made a customization for my token claims, with the success superuser account I just created.

Here are some of the error message :

enter image description here

enter image description here

Here are the some of the files attatched below :

models.py

from django.db import models   
from django.contrib.auth.models import AbstractBaseUser,BaseUserManager
from django.utils.translation import ugettext_lazy as _
from phone_field import PhoneField

class RegisterUserManager(BaseUserManager):

    def create_user(self, phone_number,password):

        if not phone_number:
            raise ValueError('The phone number must be set')

        user = self.model(
            phone_number=phone_number,
            password = password,)

        user.save(using = self._db)
       
        return user
        
    def create_superuser(self,phone_number,password, **extra_fields):

        user = self.create_user(
            phone_number,
            password = password
        )

        user.is_admin =  True
        user.save(using= self._db)

        return user


class RegisterUser(AbstractBaseUser):
    first_name = models.CharField(name = 'first_name',max_length=255,default = '')
    last_name = models.CharField(name='last_name', max_length=255,default = '')
    email = models.EmailField(name='email', max_length = 255)
    phone_number = PhoneField(name='phone_number',unique=True)
    birthday = models.DateField(name ='birthday',null= True)
    nickname = models.CharField(max_length=100,name = 'nickname')
    is_active = models.BooleanField(default = True)
    is_admin = models.BooleanField(default= False)
    last_login = models.DateTimeField(auto_now= True)

    USERNAME_FIELD = 'phone_number'
    REQUIRED_FIELDS = []

    objects = RegisterUserManager()

    def __str__(self):
        return self.phone_number

    def has_perm(self, perm, obj = None):
        return True

    def has_module_perms(self,perm,obj = None):
        return True

    @property
    def is_staff(self):
        return self.is_admin

views.py

from django.shortcuts import render
from django.http import HttpResponse,JsonResponse   
from rest_framework.parsers import JSONParser
from restaccount.models import RegisterUser
# Login
from restaccount.serializers import RegisterSerializers,LoginSerializer
# LoginSerializers
from django.views.decorators.csrf import csrf_exempt
from rest_framework.generics import CreateAPIView

from rest_framework_simplejwt.views import TokenObtainPairView

from rest_framework.permissions import (AllowAny,IsAuthenticated)
# from rest_framework.generics import CreateAPIView

class RegisterView(CreateAPIView):
    permission_classes = (AllowAny,)
    serializer_class = RegisterSerializers
    queryset = RegisterUser.objects.all()

class LoginView(TokenObtainPairView):
    serializer_class = LoginSerializer

serializers.py

from rest_framework.serializers import (ModelSerializer,ValidationError)
from restaccount.models import RegisterUser
# Login

from rest_framework_simplejwt.serializers import TokenObtainPairSerializer

from rest_framework import serializers

class RegisterSerializers(ModelSerializer):
    class Meta:
        model = RegisterUser
        fields =['id',
                'first_name',
                'last_name',
                'email',
                'password',
                'phone_number',
                'nickname',
                'birthday',
                ]

    def create(self,validated_data):
        first_name = validated_data['first_name']
        last_name = validated_data['last_name']
        email = validated_data['email']
        password = validated_data['password']
        phone_number = validated_data['phone_number']
        nickname = validated_data['nickname']
        birthday = validated_data['birthday']
        user_obj = RegisterUser(
            first_name = first_name,
            last_name = last_name,
            email = email,
            password = password,
            phone_number = phone_number,
            nickname = nickname,
            birthday = birthday,
        )
        user_obj.save()
        return user_obj

    def update(self, instance,validated_data):
        instance.first_name = validated_data.get('first_name',instance.first_name)
        instance.last_name = validated_data.get('last_name', instance.last_name)
        instance.email = validated_data.get('email', instance.email)
        instance.password = validated_data.get('password', instance.password)
        instance.phone_number = validated_data.get('phone_number', instance.phone_number)
        instance.nickname = validated_data.get('nickname', instance.nicknames)
        instance.birthday = validated_data.get('birthday',instance.birthday)
        instance.save()
        return instance

    def validate(self,data):
        return data
    
    def validate_phone_number(self,value):
        phone_number = value
        user_qs = RegisterUser.objects.filter(phone_number = phone_number)
        if user_qs.exists():
            raise ValidationError("This phone number is registered")
        return value


class LoginSerializer(TokenObtainPairSerializer):

    @classmethod
    def get_token(cls,user):
        token = super().get_token(user)

        token['phone_number'] = user.phone_number
        token['password'] = user.password

        return token

    def validate(self,attrs):
        data = super().validate(attrs)

        refresh = self.get_token(self.user)
        data['refresh'] = str(refresh)
        data['access'] = str(refresh.access_token)

        data['phone_number'] = self.user.phone_number

        return data

1

1 Answers

0
votes

Turns out that the password field in the model have to be hashed such that user.set_password(password). This is also the same case, if you want to create a user from the API endpoint. You have to store the hashed password in your database.

However, I don't know why this is the behaviour.