Django and JWT: How to Set Up a Secure Authentication System

RenanRenan
6 min read

Hello World! 💻

I’m thrilled to have you here as we embark on an exciting journey into the world of web development with Django. In this post, we’ll be diving into a crucial topic that many developers encounter: implementing JSON Web Tokens (JWT) for authentication in Django applications.

As you may know, securing user data and ensuring smooth authentication processes are vital in today’s web applications. JWT offers a modern, efficient way to handle user sessions without the need for server-side storage, making it a popular choice for developers across the globe.

Whether you’re a seasoned Django veteran or just starting out, this guide will provide you with clear, actionable steps to integrate JWT into your project seamlessly. Together, we’ll explore the benefits of JWT, walk through the implementation process, and ensure your application is both secure and user-friendly.

So, grab your favorite beverage, settle in, and let’s get started on this exciting journey toward mastering JWT in Django! 🚀

Feel free to check out the full source code here.

Why use JWT with Django?

Using JSON Web Tokens (JWT) with Django offers several advantages that enhance the security and efficiency of web applications. Here are some key reasons to consider implementing JWT in your Django projects:

  1. Stateless Authentication

  2. Enhanced Security

  3. Flexibility in Data Storage

  4. Easy Token Refresh

  5. Compatibility with Modern Frameworks

Now let’s get started!

1. Setting Up Our Django Project 🐍

First, make sure you have a Django project with an app already set up. If you don't have one, you can create it using these commands:

django-admin startproject project_name
cd project_name
python manage.py startapp app_name

And let's make sure we have a database to simulate the desired login functionality.

python manage.py makemigrations
python manage.py migrate

If you encountered difficulties executing the previous commands, it may indicate that Django (or Python) is not installed in your environment. To assist you, please refer to the following link for detailed instructions on how to install Django.

https://docs.djangoproject.com/en/5.1/intro/install/

Feel free to let me know if you need any further adjustments!

2. Installing Required Packages

We will need to install Django Rest Framework and Simple JWT. We can do this by running:

pip install djangorestframework djangorestframework-simplejwt

After installation, add the necessary applications to your INSTALLED_APPS list in the settings.py file:

INSTALLED_APPS = [
    ...,
    'rest_framework',
    'rest_framework_simplejwt',
]

Also, don't forget to add your own app to the list of installed apps.

INSTALLED_APPS = [
    ...,
    'your_own_app'
]

3. Configuring Django Rest Framework

In your settings.py, configure DRF to use Simple JWT as the default authentication class:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ),
}

You can also define JWT settings, such as token lifetime and whether to use a blacklist:

from datetime import timedelta

SIMPLE_JWT = {
    'ACCESS_TOKEN_LIFETIME': timedelta(minutes=5),
    'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
    'ROTATE_REFRESH_TOKENS': True,
    'BLACKLIST_AFTER_ROTATION': True,
}

4. Creating User Models and Serializers

Define a custom user model if needed, and create serializers for user registration and authentication. We will create a serializers.py file and write a serializer function. It should look like this example:

python from django.contrib.auth.models import User
from rest_framework import serializers

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User fields = ['id', 'username', 'email', 'password']
        extra_kwargs = {'password': {'write_only': True}}

    def create(self, validated_data):
        user = User(**validated_data)}
        user.set_password(validated_data['password']) # Hash the password
        user.save()
        return user

Note: We are creating this file inside the app folder, not the project folder.

You can view the complete project source code at this link: https://github.com/bluesoc/DjangoJWTAuth

5. Creating Views for Authentication

We will need views to handle user registration and token generation. Using Django Rest Framework (DRF) generic views, we can create these endpoints (on the views.py file):

from rest_framework import generics
from rest_framework_simplejwt.views import TokenObtainPairView
from .serializers import UserSerializer

class RegisterView(generics.CreateAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer 

class CustomTokenObtainPairView(TokenObtainPairView):
    # You can customize the token response here if needed
    pass

6. Setting Up URLs ⚙️

In your app's urls.py, set up the routes for your authentication views:

from django.urls import path 
from .views import RegisterView, CustomTokenObtainPairView 

urlpatterns = [ 
    path('register/', [ RegisterView.as ](http://RegisterView.as) _view(), name='register'), 
    path('login/', CustomTokenObtainPairView.as_view(), name='token_obtain_pair'), 
]

It's done! We are ready to go! 🚀

The authentication backend should be working now, and you can access it via the 'register' and 'login' URLs. These endpoints will allow you to create a user and log in afterward.

7. Protecting API Endpoints 🛡️

To protect a specific API endpoint or view, you can use the IsAuthenticated permission class from Django Rest Framework (DRF). For example:

from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView

class PrivateView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        return Response({'message': 'Access Granted!'})

Let's not forget to add the URL in the urls.py file:

from .views import PrivateView

urlpatterns = [
    ...,
    path('private/', PrivateView.as_view(), name='private'),
]

8. Let's interact with the backend! 🧪

First, let's start our server with the following command:

python manage.py runserver

Since our server is running, let's interact with our endpoints at register/, login/, and private/. If you try to access them using your browser, you should see HTML forms at the end of the page. For example, visit http://localhost:8000/register/.

After registering a user, logging in, and making a GET request to private/ with your token, you should see this response:

{
    "message": "Access Granted!"
}

We are done! Congratulations on making it this far!


Final thoughts on Building Authentication Systems

Remember, the default HTTP protocol is not safe for transmitting private or sensitive information. Using HTTP methods with JSON Web Tokens (JWT) for transmitting private data can pose security risks due to several reasons:

  1. Exposure of Sensitive Information

  2. Lack of Confidentiality

  3. Token Theft and Replay Attacks

Best Practices for Secure Transmission

To mitigate these risks, consider the following best practices when using JWTs:

  • Use HTTPS: Always transmit JWTs over HTTPS to encrypt the data in transit, preventing interception by attackers.

  • Avoid Sensitive Data in Payload: Do not include sensitive information in the JWT payload. Instead, use identifiers that can be used to look up sensitive data on the server side.

  • Implement Short Expiration Times: Set short expiration times for JWTs to limit the window of opportunity for an attacker if a token is compromised.

  • Use Secure Storage: Store JWTs securely on the client side (e.g., in memory or secure HTTP-only cookies) to minimize the risk of exposure.

As you embark on your journey to learn more about application security and best practices, remember that every step you take brings you closer to becoming a more proficient developer. The landscape of technology is ever-evolving, and staying informed about the latest security measures is crucial in today’s digital world.


SimpleJWT Documentation: https://django-rest-framework-simplejwt.readthedocs.io/en/latest/index.html

DjangoJWTAuth Repository Source Code: https://github.com/bluesoc/DjangoJWTAuth

0
Subscribe to my newsletter

Read articles from Renan directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Renan
Renan

Software Developer & Cybersecurity Analyst