JSON Web Token based authentication for Django REST framework
—
Comprehensive configuration system for customizing JWT behavior including token expiration, algorithms, secret keys, and handler functions. The settings system provides centralized control over all JWT authentication aspects.
Central configuration object providing access to all JWT settings with defaults and validation.
from rest_framework_jwt.settings import api_settings
# Access configuration values
api_settings.JWT_SECRET_KEY: str
api_settings.JWT_ALGORITHM: str
api_settings.JWT_EXPIRATION_DELTA: timedelta
api_settings.JWT_ALLOW_REFRESH: bool
api_settings.JWT_AUTH_HEADER_PREFIX: str
# ... and all other JWT settings# Module-level configuration objects
USER_SETTINGS: Optional[Dict[str, Any]]
"""User-defined JWT_AUTH settings from Django settings module."""
DEFAULTS: Dict[str, Any]
"""Default values for all JWT configuration options."""
IMPORT_STRINGS: Tuple[str, ...]
"""Settings that should be imported as functions or classes."""
api_settings: APISettings
"""Main configuration object with merged user settings and defaults."""Customizable functions that control JWT token processing and validation.
# Token Processing Handlers
JWT_ENCODE_HANDLER: str = 'rest_framework_jwt.utils.jwt_encode_handler'
"""Function to encode JWT payloads into token strings."""
JWT_DECODE_HANDLER: str = 'rest_framework_jwt.utils.jwt_decode_handler'
"""Function to decode and validate JWT token strings."""
JWT_PAYLOAD_HANDLER: str = 'rest_framework_jwt.utils.jwt_payload_handler'
"""Function to generate JWT payload from user instance."""
JWT_PAYLOAD_GET_USERNAME_HANDLER: str = 'rest_framework_jwt.utils.jwt_get_username_from_payload_handler'
"""Function to extract username from JWT payload."""
JWT_PAYLOAD_GET_USER_ID_HANDLER: str = 'rest_framework_jwt.utils.jwt_get_user_id_from_payload_handler'
"""Function to extract user ID from JWT payload (deprecated)."""
JWT_RESPONSE_PAYLOAD_HANDLER: str = 'rest_framework_jwt.utils.jwt_response_payload_handler'
"""Function to format JWT response data."""
JWT_GET_USER_SECRET_KEY: Optional[str] = None
"""Function to generate user-specific secret keys."""Security-related configuration for JWT signing and verification.
JWT_SECRET_KEY: str = settings.SECRET_KEY
"""Secret key for HMAC-based JWT signing (default: Django SECRET_KEY)."""
JWT_PRIVATE_KEY: Optional[str] = None
"""Private key for RSA/ECDSA JWT signing."""
JWT_PUBLIC_KEY: Optional[str] = None
"""Public key for RSA/ECDSA JWT verification."""
JWT_ALGORITHM: str = 'HS256'
"""Algorithm for JWT signing and verification."""
JWT_VERIFY: bool = True
"""Whether to verify JWT signatures."""
JWT_VERIFY_EXPIRATION: bool = True
"""Whether to verify JWT expiration times."""
JWT_LEEWAY: int = 0
"""Leeway in seconds for expiration verification."""Configuration for token expiration and refresh behavior.
JWT_EXPIRATION_DELTA: timedelta = timedelta(seconds=300)
"""Token lifetime (default: 5 minutes)."""
JWT_ALLOW_REFRESH: bool = False
"""Whether to allow token refresh."""
JWT_REFRESH_EXPIRATION_DELTA: timedelta = timedelta(days=7)
"""Maximum time allowed for token refresh."""Configuration for how tokens are transmitted and processed.
JWT_AUTH_HEADER_PREFIX: str = 'JWT'
"""Prefix for Authorization header (e.g., 'Authorization: JWT <token>')."""
JWT_AUTH_COOKIE: Optional[str] = None
"""Cookie name for JWT storage (enables cookie-based authentication)."""Optional JWT standard claims for enhanced security.
JWT_AUDIENCE: Optional[str] = None
"""JWT audience claim for token validation."""
JWT_ISSUER: Optional[str] = None
"""JWT issuer claim for token validation."""# In Django settings.py
JWT_AUTH = {
'JWT_SECRET_KEY': 'your-secret-key-here',
'JWT_ALGORITHM': 'HS256',
'JWT_EXPIRATION_DELTA': timedelta(hours=1),
'JWT_ALLOW_REFRESH': True,
'JWT_REFRESH_EXPIRATION_DELTA': timedelta(days=7),
'JWT_AUTH_HEADER_PREFIX': 'Bearer', # Change from 'JWT' to 'Bearer'
}import datetime
JWT_AUTH = {
# Use environment variable for secret key
'JWT_SECRET_KEY': os.environ.get('JWT_SECRET_KEY', settings.SECRET_KEY),
# Strong algorithm
'JWT_ALGORITHM': 'HS256',
# Reasonable token lifetime
'JWT_EXPIRATION_DELTA': datetime.timedelta(minutes=15),
# Enable refresh with limited window
'JWT_ALLOW_REFRESH': True,
'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(hours=24),
# Enable verification
'JWT_VERIFY': True,
'JWT_VERIFY_EXPIRATION': True,
'JWT_LEEWAY': 10, # 10 seconds leeway for clock skew
# Add audience and issuer claims
'JWT_AUDIENCE': 'myapp-api',
'JWT_ISSUER': 'myapp.com',
# Use cookie for web clients
'JWT_AUTH_COOKIE': 'jwt-token',
}# Custom payload handler
def custom_jwt_payload_handler(user):
return {
'user_id': user.id,
'username': user.username,
'email': user.email,
'is_staff': user.is_staff,
'groups': [group.name for group in user.groups.all()],
'exp': datetime.utcnow() + api_settings.JWT_EXPIRATION_DELTA,
'iat': datetime.utcnow(),
}
# Custom response handler
def custom_jwt_response_handler(token, user=None, request=None):
return {
'token': token,
'user': {
'id': user.id,
'username': user.username,
'email': user.email,
'full_name': user.get_full_name(),
},
'expires': (datetime.utcnow() + api_settings.JWT_EXPIRATION_DELTA).isoformat(),
}
# User-specific secret key for token invalidation
def get_user_secret_key(user):
# Tokens become invalid when user password changes
return f"{settings.SECRET_KEY}:{user.password[:10]}"
# Configuration
JWT_AUTH = {
'JWT_PAYLOAD_HANDLER': 'myapp.utils.custom_jwt_payload_handler',
'JWT_RESPONSE_PAYLOAD_HANDLER': 'myapp.utils.custom_jwt_response_handler',
'JWT_GET_USER_SECRET_KEY': 'myapp.utils.get_user_secret_key',
}# For RSA-based signing (more secure but requires key management)
JWT_AUTH = {
'JWT_ALGORITHM': 'RS256',
'JWT_PRIVATE_KEY': '''-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA...
-----END RSA PRIVATE KEY-----''',
'JWT_PUBLIC_KEY': '''-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A...
-----END PUBLIC KEY-----''',
}import os
from datetime import timedelta
# Load from environment variables for different deployment environments
JWT_AUTH = {
'JWT_SECRET_KEY': os.getenv('JWT_SECRET_KEY', settings.SECRET_KEY),
'JWT_ALGORITHM': os.getenv('JWT_ALGORITHM', 'HS256'),
'JWT_EXPIRATION_DELTA': timedelta(
seconds=int(os.getenv('JWT_EXPIRATION_SECONDS', '900')) # 15 min default
),
'JWT_ALLOW_REFRESH': os.getenv('JWT_ALLOW_REFRESH', 'false').lower() == 'true',
'JWT_REFRESH_EXPIRATION_DELTA': timedelta(
hours=int(os.getenv('JWT_REFRESH_HOURS', '24'))
),
'JWT_AUTH_HEADER_PREFIX': os.getenv('JWT_AUTH_HEADER_PREFIX', 'JWT'),
'JWT_AUTH_COOKIE': os.getenv('JWT_AUTH_COOKIE'), # None if not set
'JWT_AUDIENCE': os.getenv('JWT_AUDIENCE'),
'JWT_ISSUER': os.getenv('JWT_ISSUER'),
}from rest_framework_jwt.settings import api_settings
# Access individual settings
secret_key = api_settings.JWT_SECRET_KEY
algorithm = api_settings.JWT_ALGORITHM
expiration = api_settings.JWT_EXPIRATION_DELTA
# Check if refresh is enabled
if api_settings.JWT_ALLOW_REFRESH:
# Handle refresh logic
pass
# Get handler functions
payload_handler = api_settings.JWT_PAYLOAD_HANDLER
encode_handler = api_settings.JWT_ENCODE_HANDLER# Settings can be modified at runtime (not recommended for production)
from rest_framework_jwt.settings import api_settings
from django.test import override_settings
# In tests
with override_settings(JWT_AUTH={'JWT_EXPIRATION_DELTA': timedelta(seconds=1)}):
# Test with very short token lifetime
pass# If a handler function path is invalid
JWT_AUTH = {
'JWT_PAYLOAD_HANDLER': 'nonexistent.module.function',
}
# Results in ImportError when api_settings is accessed
try:
from rest_framework_jwt.settings import api_settings
handler = api_settings.JWT_PAYLOAD_HANDLER
except ImportError as e:
print(f"Invalid handler configuration: {e}")# Required (have defaults)
- JWT_SECRET_KEY (defaults to Django SECRET_KEY)
- JWT_ALGORITHM (defaults to 'HS256')
- JWT_EXPIRATION_DELTA (defaults to 5 minutes)
# Optional (None by default)
- JWT_PRIVATE_KEY
- JWT_PUBLIC_KEY
- JWT_AUTH_COOKIE
- JWT_AUDIENCE
- JWT_ISSUER
- JWT_GET_USER_SECRET_KEY# DO: Use environment variables for secrets
JWT_AUTH = {
'JWT_SECRET_KEY': os.environ['JWT_SECRET_KEY'],
}
# DON'T: Hard-code secrets in settings files
JWT_AUTH = {
'JWT_SECRET_KEY': 'hardcoded-secret-key', # Never do this
}# Balance security vs usability
JWT_AUTH = {
# Short-lived access tokens
'JWT_EXPIRATION_DELTA': timedelta(minutes=15),
# Reasonable refresh window
'JWT_ALLOW_REFRESH': True,
'JWT_REFRESH_EXPIRATION_DELTA': timedelta(hours=24),
}# Recommended algorithms by use case:
# High security (requires key management)
'JWT_ALGORITHM': 'RS256' # RSA with SHA-256
# Balanced (simpler key management)
'JWT_ALGORITHM': 'HS256' # HMAC with SHA-256
# Avoid weak algorithms
'JWT_ALGORITHM': 'none' # Never use this
'JWT_ALGORITHM': 'HS1' # Deprecated/weakThe configuration system provides extensive flexibility while maintaining secure defaults for JWT authentication behavior.
Install with Tessl CLI
npx tessl i tessl/pypi-djangorestframework-jwt