When I first started working with Django REST Framework (DRF), securing APIs was always a critical concern. Over the years, I’ve found JSON Web Tokens (JWT) to be one of the best ways to handle authentication for APIs, especially when scalability and statelessness matter. JWT allows you to transmit user information securely between client and server without the need for server-side sessions.
In this article, I’ll walk you through implementing JWT authentication in a Django REST Framework project. We’ll cover everything from setting up the environment to writing the full code example, using a real-world scenario that resonates with developers.
What is JWT Authentication?
JWT stands for JSON Web Token. It’s a compact, URL-safe means of representing claims to be transferred between two parties. In the context of web APIs, JWT is used to securely transmit user identity information after login, so the server can verify the user on subsequent requests without storing session data.
JWT tokens are self-contained, meaning all the user info and claims are included in the token itself, digitally signed to prevent tampering.
Read Python Django Length Filter
Set Up JWT Authentication in Django REST Framework
I’ll show you two common methods to implement JWT authentication:
- Using the popular djangorestframework-simplejwt package.
- A manual approach using custom token generation (for learning purposes).
Method 1: Use djangorestframework-simplejwt
This is the most recommended and widely used method. It provides ready-to-use JWT authentication classes and views.
Step 1: Install Required Packages
pip install djangorestframework
pip install djangorestframework-simplejwt
pip install djangoStep 2: Update settings.py
Add 'rest_framework' and 'rest_framework_simplejwt.authentication.JWTAuthentication' to your Django settings.
INSTALLED_APPS = [
...
'rest_framework',
]
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
),
}Step 3: Define URLs for Token Operations
In your urls.py, add routes for obtaining and refreshing tokens.
from django.urls import path
from rest_framework_simplejwt.views import (
TokenObtainPairView,
TokenRefreshView,
)
urlpatterns = [
path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
]Check out Django for Loop
Step 4: Create a Simple API View to Test Authentication
Here’s an example of a protected view that returns the logged-in user’s info:
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
class UserProfileView(APIView):
permission_classes = [IsAuthenticated]
def get(self, request):
user = request.user
return Response({
'username': user.username,
'email': user.email,
})Add this view to your URLs:
urlpatterns += [
path('api/profile/', UserProfileView.as_view(), name='user_profile'),
]Step 5: Test the JWT Authentication Flow
- Obtain Token:
Send a POST request to/api/token/with JSON body:
{
"username": "yourusername",
"password": "yourpassword"
}
You will receive:
{
"refresh": "your_refresh_token",
"access": "your_access_token"
}
- Access Protected API:
Include the access token in the Authorization header:
Authorization: Bearer your_access_tokenCall /api/profile/ and you’ll get your user info.
- Refresh Token:
Call/api/token/refresh/with the refresh token to get a new access token.

Method 2: Manual JWT Implementation (For Learning)
While I recommend using simplejwt for production, understanding how JWT works under the hood is helpful.
Step 1: Install PyJWT
pip install PyJWTStep 2: Create Token Utility Functions
import jwt
import datetime
from django.conf import settings
def generate_jwt_token(user):
payload = {
'user_id': user.id,
'username': user.username,
'exp': datetime.datetime.utcnow() + datetime.timedelta(days=1),
'iat': datetime.datetime.utcnow(),
}
token = jwt.encode(payload, settings.SECRET_KEY, algorithm='HS256')
return tokenStep 3: Create a Login API View
from django.contrib.auth import authenticate
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
class LoginAPIView(APIView):
def post(self, request):
username = request.data.get('username')
password = request.data.get('password')
user = authenticate(username=username, password=password)
if user:
token = generate_jwt_token(user)
return Response({'token': token})
return Response({'error': 'Invalid Credentials'}, status=status.HTTP_401_UNAUTHORIZED)Step 4: Create a Custom Authentication Class
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from django.contrib.auth.models import User
class JWTAuthentication(BaseAuthentication):
def authenticate(self, request):
auth_header = request.headers.get('Authorization')
if not auth_header:
return None
prefix, token = auth_header.split(' ')
if prefix.lower() != 'bearer':
return None
try:
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=['HS256'])
except jwt.ExpiredSignatureError:
raise AuthenticationFailed('Token expired')
except jwt.InvalidTokenError:
raise AuthenticationFailed('Invalid token')
user = User.objects.get(id=payload['user_id'])
return (user, token)Step 5: Protect Views Using Custom Authentication
from rest_framework.permissions import IsAuthenticated
class UserProfileView(APIView):
authentication_classes = [JWTAuthentication]
permission_classes = [IsAuthenticated]
def get(self, request):
user = request.user
return Response({
'username': user.username,
'email': user.email,
})Implementing JWT authentication in Django REST Framework is straightforward and essential for building secure, scalable APIs. The djangorestframework-simplejwt package is my go-to solution because it handles the heavy lifting and follows best practices.
If you want to understand JWT deeply, implementing a manual version is a great exercise. However, for production-ready apps, relying on battle-tested libraries ensures security and maintainability.
With JWT, your API can securely authenticate users without server-side sessions, making your backend stateless and easier to scale, perfect for modern web and mobile applications.
You may also read:

I am Bijay Kumar, a Microsoft MVP in SharePoint. Apart from SharePoint, I started working on Python, Machine learning, and artificial intelligence for the last 5 years. During this time I got expertise in various Python libraries also like Tkinter, Pandas, NumPy, Turtle, Django, Matplotlib, Tensorflow, Scipy, Scikit-Learn, etc… for various clients in the United States, Canada, the United Kingdom, Australia, New Zealand, etc. Check out my profile.