JSON Web Token based authentication for Django REST framework
—
Ready-to-use API views for JWT token operations including token generation, verification, and refresh functionality. These views provide complete HTTP endpoints for JWT authentication workflows.
Foundation class for all JWT-related API views with common functionality.
class JSONWebTokenAPIView(APIView):
permission_classes = ()
authentication_classes = ()
def get_serializer_context(self):
"""
Returns extra context for serializer.
Returns:
dict: Context containing request and view instances
"""
def get_serializer_class(self):
"""
Returns the serializer class for this view.
Returns:
class: Serializer class to use for validation
Raises:
AssertionError: If serializer_class is not defined
"""
def get_serializer(self, *args, **kwargs):
"""
Returns serializer instance for validation and processing.
Args:
*args: Positional arguments for serializer
**kwargs: Keyword arguments for serializer
Returns:
Serializer: Configured serializer instance
"""
def post(self, request, *args, **kwargs):
"""
Handles POST requests for JWT operations.
Args:
request: HTTP request object
*args: Additional positional arguments
**kwargs: Additional keyword arguments
Returns:
Response: JSON response with token data or validation errors
Response Format:
Success: {'token': '<jwt_token>', ...custom_data}
Error: {field_name: [error_messages]}
"""API view for obtaining JWT tokens through username/password authentication.
class ObtainJSONWebToken(JSONWebTokenAPIView):
serializer_class = JSONWebTokenSerializer
# Inherits post() method that:
# 1. Validates username/password via serializer
# 2. Authenticates user and generates JWT
# 3. Returns token response with optional cookie settingAPI view for verifying the validity of existing JWT tokens.
class VerifyJSONWebToken(JSONWebTokenAPIView):
serializer_class = VerifyJSONWebTokenSerializer
# Inherits post() method that:
# 1. Validates provided token via serializer
# 2. Verifies token signature and expiration
# 3. Returns token and user information if validAPI view for refreshing JWT tokens to extend their lifetime.
class RefreshJSONWebToken(JSONWebTokenAPIView):
serializer_class = RefreshJSONWebTokenSerializer
# Inherits post() method that:
# 1. Validates existing token via serializer
# 2. Checks refresh eligibility and expiration
# 3. Generates new token with extended expirationPre-configured view instances ready for URL routing.
obtain_jwt_token = ObtainJSONWebToken.as_view()
"""
Function-based view for obtaining JWT tokens.
POST /api-token-auth/
{
"username": "user@example.com",
"password": "password123"
}
Response:
{
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
}
"""
refresh_jwt_token = RefreshJSONWebToken.as_view()
"""
Function-based view for refreshing JWT tokens.
POST /api-token-refresh/
{
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
}
Response:
{
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
}
"""
verify_jwt_token = VerifyJSONWebToken.as_view()
"""
Function-based view for verifying JWT tokens.
POST /api-token-verify/
{
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
}
Response:
{
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
}
"""# urls.py
from django.urls import path
from rest_framework_jwt.views import obtain_jwt_token, refresh_jwt_token, verify_jwt_token
urlpatterns = [
path('api-token-auth/', obtain_jwt_token),
path('api-token-refresh/', refresh_jwt_token),
path('api-token-verify/', verify_jwt_token),
]from rest_framework_jwt.views import JSONWebTokenAPIView
from rest_framework_jwt.serializers import JSONWebTokenSerializer
from rest_framework.response import Response
from django.contrib.auth import authenticate
class CustomObtainJWT(JSONWebTokenAPIView):
serializer_class = JSONWebTokenSerializer
def post(self, request, *args, **kwargs):
# Add custom logic before token generation
serializer = self.get_serializer(data=request.data)
if serializer.is_valid():
# Custom authentication logging
user = serializer.object.get('user')
self.log_authentication(user, request)
# Generate response with additional data
token = serializer.object.get('token')
response_data = {
'token': token,
'user': {
'id': user.id,
'username': user.username,
'last_login': user.last_login.isoformat() if user.last_login else None,
},
'expires_in': 300,
}
return Response(response_data)
return Response(serializer.errors, status=400)
def log_authentication(self, user, request):
# Custom logging logic
passimport requests
# Test token obtainment
response = requests.post('http://localhost:8000/api-token-auth/', {
'username': 'testuser',
'password': 'testpass123'
})
if response.status_code == 200:
token = response.json()['token']
print(f"Token obtained: {token}")
# Test token verification
verify_response = requests.post('http://localhost:8000/api-token-verify/', {
'token': token
})
if verify_response.status_code == 200:
print("Token is valid")
else:
print("Token verification failed")
# Test authenticated request
headers = {'Authorization': f'JWT {token}'}
api_response = requests.get(
'http://localhost:8000/api/protected-endpoint/',
headers=headers
)
print(f"API Response: {api_response.status_code}")
else:
print(f"Authentication failed: {response.json()}")// JavaScript client-side usage
async function authenticateUser(credentials) {
try {
const response = await fetch('/api-token-auth/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': getCsrfToken(),
},
body: JSON.stringify(credentials)
});
if (response.ok) {
const data = await response.json();
localStorage.setItem('jwt_token', data.token);
return data.token;
} else {
const errors = await response.json();
throw new Error(`Authentication failed: ${JSON.stringify(errors)}`);
}
} catch (error) {
console.error('Authentication error:', error);
throw error;
}
}
async function makeAuthenticatedRequest(url, options = {}) {
const token = localStorage.getItem('jwt_token');
if (!token) {
throw new Error('No authentication token available');
}
const headers = {
'Authorization': `JWT ${token}`,
'Content-Type': 'application/json',
...options.headers,
};
return fetch(url, {
...options,
headers,
});
}{
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ1c2VybmFtZSI6InRlc3R1c2VyIiwiZXhwIjoxNjIzNzUwNDAwfQ.signature"
}{
"non_field_errors": ["Unable to log in with provided credentials."]
}{
"username": ["This field is required."],
"password": ["This field is required."]
}{
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
}{
"non_field_errors": ["Signature has expired."]
}Views automatically handle JWT cookie storage when configured:
# In settings.py
JWT_AUTH = {
'JWT_AUTH_COOKIE': 'jwt-token',
'JWT_EXPIRATION_DELTA': timedelta(hours=1),
}When JWT_AUTH_COOKIE is set, successful token obtainment will:
The views handle various error conditions:
Error responses include descriptive messages to help clients handle authentication failures appropriately.
The views module defines handler function references used by the API views:
jwt_response_payload_handler = api_settings.JWT_RESPONSE_PAYLOAD_HANDLER
"""Function reference for formatting JWT response payloads."""The JWT views implement several security best practices:
Install with Tessl CLI
npx tessl i tessl/pypi-djangorestframework-jwt