Building a System for User Registration and Login using Python (Part 1 )
Learning by Building
Application Demonstration
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
Go to Sign Up to create a new user account
Enter the required signup details and click on the Sign-Up button
If you enter incorrect details, an error message will be displayed
Lastly, let's log in the user
Prerequisite technologies and concepts:
Simple JWT (JSON Web Token authentication)
Basic understanding of API (Application Programming Interface) and HTTP requests/responses.
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
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!