JWT authentication using HTTP-only cookies for Django REST Framework.
This plugin provides secure JWT authentication by storing tokens in HTTP-only cookies instead of local storage or headers. This approach reduces XSS risks and simplifies frontend authentication handling.
- HTTP-only cookies: Tokens stored securely in browser cookies
- Automatic token refresh: Middleware handles token renewal transparently
- Fallback authentication: Supports both cookie and header-based authentication
- Session cookie support: Optional Django session cookie creation
- OpenAPI integration: Automatic API documentation with drf-spectacular
- Customizable settings: Flexible cookie configuration options
pip install django-cookiejwt- Add to
INSTALLED_APPS:
INSTALLED_APPS = [
# ... other apps
'rest_framework',
'rest_framework_simplejwt',
'rest_framework_simplejwt.token_blacklist',
'django_cookiejwt',
]- Add middleware:
MIDDLEWARE = [
# ... other middleware
'django.contrib.sessions.middleware.SessionMiddleware',
'django_cookiejwt.middlewares.RefreshTokenMiddleware',
# ... other middleware
]- Configure authentication:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'django_cookiejwt.authentication.CookieJWTAuthentication',
],
}- Include URLs:
from django.urls import path, include
urlpatterns = [
# ... your urls
path('api/auth/', include('django_cookiejwt.urls')),
]Configure cookie behavior in your Django settings:
# Cookie security settings
COOKIEJWT_HTTPONLY = True # HTTP-only cookies (recommended)
COOKIEJWT_SECURE = True # Set to False in development!
COOKIEJWT_SAMESITE = 'Lax' # CSRF protection
# Cookie naming and expiration
COOKIEJWT_ACCESS_MAX_AGE = 300 # 5 minutes
COOKIEJWT_REFRESH_MAX_AGE = 86400 # 1 day
COOKIEJWT_PATH = '/'
COOKIEJWT_DOMAIN = None
# Session cookie creation
COOKIEJWT_SET_SESSION_COOKIE = TrueImportant: The default settings are NOT secure for production use. Configure these settings before deploying:
# Production security settings
COOKIEJWT_SECURE = True # REQUIRED: HTTPS only
COOKIEJWT_SAMESITE = 'Strict' # RECOMMENDED: Strong CSRF protection
COOKIEJWT_HTTPONLY = True # REQUIRED: Prevent XSS attacks
# Optional production optimizations
COOKIEJWT_DOMAIN = 'yourdomain.com' # Restrict to your domainCritical: Never use COOKIEJWT_SECURE = False in production. This will send tokens over unencrypted HTTP connections, creating a serious security vulnerability.
The authentication system works with a fallback mechanism:
- Cookie Authentication (Primary): The system first looks for JWT tokens in HTTP-only cookies
- Header Authentication (Fallback): If no valid token is found in cookies, it falls back to standard JWT header authentication (
Authorization: Bearer <token>)
This means you can use both authentication methods simultaneously:
- Frontend applications can use cookies for seamless authentication
- API clients and mobile apps can use traditional header-based authentication
The RefreshTokenMiddleware processes every request (except /admin/ paths) and performs the following operations:
- Reads and validates access token from cookies
- Makes database queries to authenticate users
- Automatically refreshes expired tokens when possible
This provides seamless user experience but adds processing overhead to each request. Consider this when designing high-traffic applications.
Send login credentials to the token endpoint:
curl -X POST http://localhost:8000/api/auth/token/ \
-H "Content-Type: application/json" \
-d '{"username": "user", "password": "pass"}'The response will set HTTP-only cookies containing JWT tokens.
Traditional JWT authentication also works:
curl -X GET http://localhost:8000/api/protected-endpoint/ \
-H "Authorization: Bearer <your-jwt-token>"Blacklist the refresh token:
curl -X POST http://localhost:8000/api/auth/token/blacklist/ \
-H "Content-Type: application/json" \
-d '{"refresh": ""}'This will clear the authentication cookies.
With cookies set, authenticated requests work automatically:
// No need to handle tokens manually
fetch('/api/protected-endpoint/', {
credentials: 'include' // Include cookies
})- Login: User credentials are exchanged for JWT tokens stored in HTTP-only cookies
- Requests: Cookies are automatically sent with each request
- Authentication: System checks cookies first, then falls back to Authorization header
- Refresh: Middleware automatically refreshes expired access tokens using the refresh token
- Logout: Refresh token is blacklisted and cookies are cleared
- XSS Protection: HTTP-only cookies prevent JavaScript access to tokens
- CSRF Mitigation: SameSite cookie attribute provides CSRF protection
- Automatic Handling: No manual token management required on frontend
- Flexible Integration: Supports both cookie and header authentication
POST /api/auth/token/- Obtain JWT tokens (login)POST /api/auth/token/blacklist/- Blacklist refresh token (logout)
- Django >= 4.0
- Django REST Framework >= 3.14.0
- djangorestframework-simplejwt >= 5.2.0
- drf-spectacular >= 0.28.0
- Python >= 3.12
MIT License
Issues and pull requests are welcome on GitHub.