JSON Web Token for Django REST Framework
djangorestframework-jwt provides JSON Web Token (JWT) based authentication for Django REST Framework. While historically popular, the library is largely unmaintained with its last release (1.11.0) in October 2017. Users are generally recommended to migrate to more actively maintained alternatives like `drf-simplejwt` for current Django and DRF versions, as this library lacks recent security updates and compatibility testing with newer Django/DRF releases.
Common errors
-
ModuleNotFoundError: No module named 'rest_framework_jwt'
cause The `djangorestframework-jwt` library is either not installed or not correctly added to your Django project's `INSTALLED_APPS`.fixRun `pip install djangorestframework-jwt` and ensure `'rest_framework_jwt'` is included in your `INSTALLED_APPS` list in `settings.py`. -
rest_framework_jwt.exceptions.InvalidTokenError: Signature has expired.
cause The provided JSON Web Token has exceeded its `JWT_EXPIRATION_DELTA` and is no longer considered valid.fixObtain a new token by re-authenticating or using the refresh token endpoint (`api/token/refresh/`) if refresh tokens are enabled and valid. You can adjust `JWT_EXPIRATION_DELTA` and `JWT_REFRESH_EXPIRATION_DELTA` in `settings.py` to change token lifetimes. -
django.core.exceptions.ImproperlyConfigured: JWT_AUTH setting is missing or improperly configured.
cause Essential settings for `JWT_AUTH`, such as `JWT_SECRET_KEY`, are missing or incorrectly defined in your `settings.py`.fixReview your `JWT_AUTH` dictionary in `settings.py`. Ensure all mandatory keys (like `JWT_SECRET_KEY`) are present and correctly formatted according to the `djangorestframework-jwt` documentation. -
rest_framework.exceptions.AuthenticationFailed: Signature verification failed.
cause The JWT signature could not be verified, likely due to an incorrect `JWT_SECRET_KEY` being used for decoding, or a tampered/corrupted token.fixVerify that the `JWT_SECRET_KEY` in your `settings.py` exactly matches the key used to encode the token. If running multiple services, ensure they share the same secret key. Obtain a new token to rule out token corruption.
Warnings
- gotcha This library is largely unmaintained since its last release in 2017. It may lack security updates and compatibility with recent Django and Django REST Framework versions. For new projects or migrations, consider using `drf-simplejwt` or other actively maintained alternatives.
- breaking Official support for Django REST Framework 2.x and older Django versions (pre-1.8) was dropped in version 1.8.0. Using `djangorestframework-jwt` with unsupported versions may lead to unexpected errors or vulnerabilities.
- gotcha Using a static or easily discoverable `JWT_SECRET_KEY` directly in `settings.py` is a severe security vulnerability. This key is used to sign and verify JWTs, and its compromise allows attackers to forge tokens.
- breaking The `verify_expiration` argument for PyJWT's `decode` function was removed in PyJWT 1.0.0. `djangorestframework-jwt` version 1.5.0 and later fixed this incompatibility, but older versions might fail if using PyJWT >= 1.0.0.
Install
-
pip install djangorestframework-jwt
Imports
- JSONWebTokenAuthentication
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
- obtain_jwt_token
from rest_framework_jwt.views import obtain_jwt_token
- refresh_jwt_token
from rest_framework_jwt.views import refresh_jwt_token
- verify_jwt_token
from rest_framework_jwt.views import verify_jwt_token
Quickstart
import os
import datetime
# settings.py
INSTALLED_APPS = [
# ... other apps
'rest_framework',
'rest_framework_jwt',
]
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
# 'rest_framework.authentication.SessionAuthentication', # Optional
# 'rest_framework.authentication.BasicAuthentication', # Optional
),
}
JWT_AUTH = {
'JWT_RESPONSE_PAYLOAD_HANDLER': 'your_project_name.utils.jwt_response_payload_handler', # Customize response data
'JWT_SECRET_KEY': os.environ.get('DJANGO_SECRET_KEY', 'insecure-dev-secret-key'), # IMPORTANT: Use a strong, unique key from env var in production
'JWT_ALLOW_REFRESH': True,
'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=3600), # Token valid for 1 hour
'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=7), # Refresh token valid for 7 days
# ... other settings
}
# your_project_name/urls.py
from django.urls import path
from rest_framework_jwt.views import obtain_jwt_token, refresh_jwt_token, verify_jwt_token
urlpatterns = [
# ... your other urls
path('api/token/', obtain_jwt_token, name='api_token_auth'),
path('api/token/refresh/', refresh_jwt_token, name='api_token_refresh'),
path('api/token/verify/', verify_jwt_token, name='api_token_verify'),
]