0
votes

I am currently developing an android chat app. I am very new to Android Studio, JWT Token Authorization, and Django Rest Framework. Right now I am having issue to work on the Django side.

So basically I was setting up a login page from my Android, and I want it to login using phone number and password as the needed credentials. However, I also want to use JWT Token Auth to make my application more secure.

Currently I have my project urls.py pointing to one of the JWT Token API

urls.py

from django.contrib import admin
from django.urls import path,include
from django.conf.urls import include, url
from rest_framework_simplejwt import views as jwt_views



urlpatterns = [
    path('admin/', admin.site.urls),
    path('account/',include('restaccount.urls')) ,
    path('api/token/', jwt_views.TokenObtainPairView.as_view(), name='token_obtain_pair'),
    path('api/token/refresh/', jwt_views.TokenRefreshView.as_view(), name='token_refresh'),
]   

This would lead to the server page which was enter image description here

*PS : The phone number fields should be the default username field..(I have made some trial modifications on my code prior I post this).

I also have set up a models that was inherit from AbstractUser

models.py

class RegisterUser(AbstractUser):
    phone_number = PhoneField(name='phone_number',unique=True)
    birthday = models.DateField(name ='birthday',null= True)
    nickname = models.CharField(max_length=100,name = 'nickname')

    def __str__(self):
        return self.phone_number

Currently I have tried to make a lot of modifications to my model, like :

  • change username = None
  • REQUIRED_FIELDS = []
  • USERNAME_FIELDS = 'phone_number'

I realize that the Token Obtain Pair View is following the Django Administration page in terms of the information that you needed (username and password).

However when I modified, I try to create superuser and try to login too Django Admin with my modified data..But I still cannot log in.. Also, I try to get token from the superuser that I have made, but it will response in "detail": "No active account found with the given credentials"

Can somebody enlighten me of the steps that I should take now?? I have tried to look for solutions but none of them solve my problem

Here's the point TLDR:

  1. I want my app to Login using phone number and password and want to use JWT Token Auth to make it secure.
  2. I realize the ObtainTokenPair view follows Django Admin credentials, so I have tried to modify my backend to be "log in" using phone number and password.
  3. After I modified, I can't login to Django Admin and cannot get token with the superuser I created.

Here some of the related file attach: Settings.py

"""
Django settings for androidapp project.

Generated by 'django-admin startproject' using Django 3.0.7.

For more information on this file, see
https://docs.djangoproject.com/en/3.0/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.0/ref/settings/
"""

import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '6qdk058^8b2@-pnw!cr1pbd(sao)vj+v69&4874zjh95xu7pg)'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = ['172.31.120.211',]


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    
    'rest_framework',

    'restaccount',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'androidapp.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'androidapp.wsgi.application'


# Database
# https://docs.djangoproject.com/en/3.0/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'Orbital',
        'USER' :'SomeUser',
        'PASSWORD':'Pass',
        'HOST' : 'localhost',
        'PORT' : '',
    }
}


# Password validation
# https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/3.0/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = False

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.0/howto/static-files/

STATIC_URL = '/static/'

AUTH_USER_MODEL = 'restaccount.RegisterUser'


#FORMAT FOR DATE INPUT  
DATE_INPUT_FORMATS = ('%d-%m-%Y', '%d/%m/%Y', '%d/%m/%y', '%d %b %Y',
                      '%d %b, %Y', '%d %b %Y', '%d %b, %Y', '%d %B, %Y',
                      '%d %B %Y')

#Format for date-time input format   
DATETIME_INPUT_FORMATS = ('%d/%m/%Y %H:%M:%S', '%d/%m/%Y %H:%M', '%d/%m/%Y',
                          '%d/%m/%y %H:%M:%S', '%d/%m/%y %H:%M', '%d/%m/%y',
                          '%Y-%m-%d %H:%M:%S', '%Y-%m-%d %H:%M', '%Y-%m-%d')

# Adding REST_FRAMEWORK SETTING WITH JWT AUTHENTICATION
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ],
}

# AUTHENTICATION_BACKENDS = (
#     'django.contrib.auth.backends.ModelBackend',
#     'restaccount.backends.UserBackend'
# )

RegisterUserManager inside models.py

class RegisterUserManager(BaseUserManager):

    def create_user(self, phone_number,password, **extra_fields):
        if not phone_number:
            raise ValueError('The phone number must be set')

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

        user.save()
       
        return user
        
    def create_superuser(self,phone_number,password, **extra_fields):
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)
        extra_fields.setdefault('is_active', True)

        # print(phone_number)

        if extra_fields.get('is_staff') is not True:
            raise ValueError(_('Superuser must have is_staff=True.'))
        if extra_fields.get('is_superuser') is not True:
            raise ValueError(_('Superuser must have is_superuser=True.'))

        return self.create_user(phone_number, password,**extra_fields)
1
sorry man,new to stackoverflow as well @jpsHeinrich

1 Answers

0
votes

Its quite difficult to pin point the bug without getting hands-on to the actual project. I can't not find the bug or fix your project. that you have to do on your own. But I can surely share what I think would help you avoid bug and fix your project.

what I could understand

  1. you want a custom user model
  2. your want to use jwt authentication

so, let's begin. User model and authentication are two different things. create Custom User model first.

  1. firstly, remove all users from database

  2. create Custom User model following this 'A full example' exactly (check by creating superuser if custom user model is working properly, if not that means you missed something try again)

  3. If you have successfully created custom user model that means you now have substituted 'username' with 'phone number' (in your case)

  4. for authentication you can use custom authentication or as you tried you can use existing packages. Configure it to act as default authentication backend.

  5. your choice of authentication package should take username and password, check if there is a user match those credentials create a token and return that token. you don't need to modify the authentication process you just provide username field(phone number) and password. Now here you might need to do something like

    {username: phone_number, password: password}

because your authentication package might not support custom user. hope it helps.