JWT Authentication0%

JWT Authentication

Beginner12 min read•Updated: Jul 11, 2026
Study MaterialsCheatsheet

DRF JWT Authentication with SimpleJWT

While standard database tokens require an SQL query on every single HTTP request, JSON Web Tokens (JWT) provide stateless, cryptographically signed authentication. The enterprise standard library for JWT in Django is djangorestframework-simplejwt. It implements short-lived Access Tokens and long-lived Refresh Tokens with built-in token rotation.


1. Dual-Token JWT Architecture

Output
1. Client POST /api/token/ (credentials) ──► Returns: { access: "...", refresh: "..." }
2. Client calls API with: Authorization: Bearer <access_token> (Valid for 5-15 mins)
3. Access token expires (401 Unauthorized)
4. Client POST /api/token/refresh/ (refresh_token) ──► Returns fresh <access_token>

2. Installation & Setup

Bash / Terminal
pip install djangorestframework-simplejwt

Configure JWTAuthentication in settings.py:

Python
# config/settings.py
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": [
"rest_framework_simplejwt.authentication.JWTAuthentication",
],
}

3. Registering JWT Endpoints in urls.py

Python
# config/urls.py
from django.urls import path
from rest_framework_simplejwt.views import (
TokenObtainPairView,
TokenRefreshView,
TokenVerifyView,
)
 
urlpatterns = [
# 1. Login / Obtain token pair
path("api/token/", TokenObtainPairView.as_view(), name="token_obtain_pair"),
# 2. Silent refresh
path("api/token/refresh/", TokenRefreshView.as_view(), name="token_refresh"),
# 3. Verify validity
path("api/token/verify/", TokenVerifyView.as_view(), name="token_verify"),
]

4. Customizing JWT Lifetimes & Rotation Settings

Python
# config/settings.py
from datetime import timedelta
 
SIMPLE_JWT = {
"ACCESS_TOKEN_LIFETIME": timedelta(minutes=15), # Short-lived access
"REFRESH_TOKEN_LIFETIME": timedelta(days=7), # Long-lived refresh
"ROTATE_REFRESH_TOKENS": True, # Issue NEW refresh token on refresh
"BLACKLIST_AFTER_ROTATION": True, # Invalidate old refresh token!
"UPDATE_LAST_LOGIN": True,
"ALGORITHM": "HS256",
"SIGNING_KEY": SECRET_KEY,
"AUTH_HEADER_TYPES": ("Bearer",), # Expects: Authorization: Bearer <token>
"USER_ID_FIELD": "id",
"USER_ID_CLAIM": "user_id",
}

5. Adding Custom Claims to Tokens

By default, JWTs only include user_id. You can embed custom claims (like email, role, or tenant_id) to avoid database lookups on client frontends:

Python
# accounts/tokens.py
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework_simplejwt.views import TokenObtainPairView
 
class CustomTokenObtainPairSerializer(TokenObtainPairSerializer):
@classmethod
def get_token(cls, user):
token = super().get_token(user)
 
# Inject custom claims into the signed JWT payload:
token["email"] = user.email
token["role"] = getattr(user, "role", "viewer")
token["organization_id"] = str(user.organization.id) if getattr(user, "organization", None) else None
 
return token
 
class CustomTokenObtainPairView(TokenObtainPairView):
serializer_class = CustomTokenObtainPairSerializer

Interactive Quiz

Practice Quiz

Question 1
What header format does SimpleJWT expect for authenticated requests?
Question 2
What security advantage does ROTATE_REFRESH_TOKENS and BLACKLIST_AFTER_ROTATION provide?
Question 3
Why are Access Tokens configured with short lifetimes (e.g. 5 to 15 minutes)?
Question 4
What does the TokenRefreshView endpoint (/api/token/refresh/) do?
Question 5
What information is contained in the signature of a JSON Web Token?
Next Lesson

Custom Permissions

Continue learning with hands-on practice, examples, and exercises in the upcoming topic.

Related Lessons

Previous LessonNext Lesson
Token AuthenticationCustom Permissions

Practice Quiz

Test your understanding of this lesson with 5 questions. Each question has one correct answer.

PrevNext