Building a System for User Registration and Login using Python (Part 1 )

Building a System for User Registration and Login using Python (Part 1 )

Learning by Building

Application Demonstration

  1. Navigate to https://verifyme-ts.netlify.app

    Note: If you are not logged in, accessing protected routes will result in being redirected to the login page

  2. Go to Sign Up to create a new user account

  3. Enter the required signup details and click on the Sign-Up button

  4. If you enter incorrect details, an error message will be displayed

  5. Lastly, let's log in the user

Prerequisite technologies and concepts:

Note: In Part 1 we are building the backend of this application using python and in Part 2 we going to utilize the APIs in the client site or frontend using React with TypeScript.

Source Code

Source code of Backend

Note: The backend/settings.py file in the source code is slightly different because it is written for deployment purposes

Developing the Backend

To begin with, we will be building the backend using Django. As a prerequisite, you should have a basic understanding of Python. If you are new to Python, it is recommended to go through some introductory materials to get familiar with the language. Once you grasp the fundamentals of Python, you can proceed to set up a Django project.

Let's start by setting up the Django project. We will then make the API endpoints for the models, which our front-end application will consume.

Check out the Django documentation on how to get started with Django


Make a directory for the backend

pip install virtualenv

Navigate to the directory

cd VerifyMe_Backend

Now make a virtual environment for this project, making a virtual environment is always a good practice to follow.

Install virtual environment by using pip

pip install virtualenv

Make a virtual environment inside the VerifyMe_Backend directory

virtualenv venv

Now, activate that virtualenv

# For windows:
./venv/Scripts/activate

# For linux:
source ./venv/bin/activate

Install django by using this command

pip install django

Initiate the project using this command

django-admin startproject backend .

Let's create a new app for managing users in Django by running

django-admin startapp users

Now, we will need some packages to build APIs, and we will also be using JWT for authentication.

Execute this command to install the required packages for this project.

pip install django-cors-headers==3.13.0 djangorestframework==3.14.0 djangorestframework-simplejwt==5.2.2

Check out this to know more about JWT (JSON web tokens)

Include 'users' and any necessary third-party tools in the installed apps list located in backend/settings.py.

# backend/settings.py

INSTALLED_APPS = [
    ......,
    # Apps
    'users',
    # Tools
    "corsheaders",
    'rest_framework',
    'rest_framework_simplejwt.token_blacklist',
]

Configure the settings for Django Rest Framework and Simple JWT

Know more about using the Django rest framework JWT

# backend/settings.py

from datetime import timedelta

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.DjangoModelPermissions',
    ),
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ),
    'DEFAULT_PARSER_CLASSES': [
        'rest_framework.parsers.JSONParser',
        'rest_framework.parsers.FormParser',
        'rest_framework.parsers.MultiPartParser'
    ]
}

SIMPLE_JWT = {
    'ACCESS_TOKEN_LIFETIME': timedelta(minutes=20),
    'REFRESH_TOKEN_LIFETIME': timedelta(days=200),
    'ROTATE_REFRESH_TOKENS': True,
    'BLACKLIST_AFTER_ROTATION': True,
    'UPDATE_LAST_LOGIN': False,

    'ALGORITHM': 'HS256',
    'SIGNING_KEY': SECRET_KEY,
    'VERIFYING_KEY': None,
    'AUDIENCE': None,
    'ISSUER': None,
    'JWK_URL': None,
    'LEEWAY': 0,

    'AUTH_HEADER_TYPES': ('Bearer',),
    'AUTH_HEADER_NAME': 'HTTP_AUTHORIZATION',
    'USER_ID_FIELD': 'id',
    'USER_ID_CLAIM': 'user_id',
    'USER_AUTHENTICATION_RULE': 'rest_framework_simplejwt.authentication.default_user_authentication_rule',

    'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
    'TOKEN_TYPE_CLAIM': 'token_type',
    'TOKEN_USER_CLASS': 'rest_framework_simplejwt.models.TokenUser',

    'JTI_CLAIM': 'jti',

    'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp',
    'SLIDING_TOKEN_LIFETIME': timedelta(minutes=20),
    'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1),
}

Go to backend/urls.py and include the path for the users app

# backend/urls.py

from django.urls import path, include

urlpatterns = [
    ......,
    path('', include('users.urls')),
]

Create a new file named urls.py inside the user's app, and add the following code

# users/urls.py

from django.urls import path
from rest_framework_simplejwt.views import ( TokenRefreshView, TokenObtainPairView)

urlpatterns = [
    path('api/token/', TokenObtainPairView.as_view(), 
name= 'token_obtain_pair'),
    path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
]

When we send a POST request with the username and password in the URL '127.0.0.1/api/token', we will receive an Access token and a Refresh token. By sending a new POST request with the previous Refresh token in the URL '127.0.0.1/api/token/refresh', we can obtain a new Access token and Refresh token.

However, before we can send the username and password to '127.0.0.1/api/token/', we need to create a URL for registering a new user. Let's do that now.

Create a new file named serializers.py and include the following code

(In case you are wondering, serializers are used to convert data into JSON format.)

# users/serializers.py

from rest_framework import serializers
from django.contrib.auth.models import User
from rest_framework.validators import UniqueValidator
from django.contrib.auth.password_validation import validate_password

class RegisterSerializer(serializers.ModelSerializer):
    email = serializers.EmailField(
        required=True,
        validators=[UniqueValidator(queryset=User.objects.all())]
    )

    password = serializers.CharField(
        write_only=True, required=True, validators=[validate_password])

    class Meta:
        model = User
        fields = ('username', 'password', 'email', 'first_name')
        extra_kwargs = {
            'first_name': {'required': True},
        }

    def create(self, validated_data):
        user = User.objects.create(
            username=validated_data['username'],
            email=validated_data['email'],
            first_name=validated_data['first_name'],
        )

        user.set_password(validated_data['password'])
        user.save()

        return user

Go to users/views.py and create a view for user registration, utilizing the serializer we just created.

# users/views.py

from rest_framework.views import APIView
from rest_framework import permissions
from .serializers import RegisterSerializer
from rest_framework.response import Response
from rest_framework import status

class RegisterView(APIView):
    permission_classes = [permissions.AllowAny]

    def post(self, request, format=None):
        serializer = RegisterSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

We have finished creating the view for user registration. Now, let's create an API endpoint for user registration.

# users/urls.py

from . import views

urlpatterns = [
    ......,
    path('register/', views.RegisterView.as_view(), name='auth_register'),
]

Execute the migrate command and then run the server using the following command.

# For migration run
python manage.py migrate

# For starting the server run
python manage.py runserver

Let's test our API endpoint using Postman

After successfully registering the user, let's try to obtain the tokens by sending the username and password to '127.0.0.1/api/token'.

Yay! We have successfully received our access and refresh tokens!


After successfully obtaining the access token and refresh token, let's use these tokens to retrieve user data.

To do this, let's create a new serializer for fetching user information.

# users/serializers.py
class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('id', 'first_name', 'username','email')

Let's create a view for retrieving user information, utilizing the serializer we just created.

# users/views.py
from django.contrib.auth.models import User
from .serializers import UserSerializer

class getUser(APIView):
    permission_classes = [permissions.IsAuthenticated]

    def get(self, request, format=None):
        serializer = UserSerializer(request.user)
        return Response(serializer.data)

Last but not least, it's time to create an API endpoint for retrieving user data, using the view and serializer we just created.

urlpatterns = [
    ......,
    path('user/', views.getUser.as_view(), name="User"),
]

To use this endpoint, we need to first send a POST request with the username and password to '127.0.0.1/api/token' and get the access token and refresh token. Then, while making a GET request to the API endpoint '127.0.0.1/user', we need to include the access token in the header. This will allow us to retrieve the user data.

Summary

This article is a tutorial on building a backend for user sign-up, login, and authentication using Python and the Django framework, along with the Django Rest Framework and Simple JWT. The article covers the steps required to build the backend, including setting up the project, creating an app for users, installing packages, configuring settings, and creating API endpoints for user registration, authentication, and data retrieval. The tutorial also includes instructions on testing the API endpoints using Postman.

Check out the Social media application build utilizing the Registration and Login system.

Thanks for reading! Have a great day, and I hope you found this article helpful. Don't forget to join us for the next part, where we'll be building the front end using React and TypeScript. See you soon!