Django Ninja JWT
Django Ninja JWT provides JSON Web Token (JWT) authentication for Django Ninja, a fast API framework for Django. It handles token creation, refresh, and authentication seamlessly within Django Ninja API routes, building upon `djangorestframework-simplejwt`. The current version is 5.4.4, with a regular release cadence focused on bug fixes and compatibility updates.
Common errors
-
django.core.exceptions.ImproperlyConfigured: The 'SIGNING_KEY' setting must not be empty.
cause The `SIMPLE_JWT['SIGNING_KEY']` setting is either not defined or explicitly set to an empty string in `settings.py`.fixSet `SIMPLE_JWT["SIGNING_KEY"]` to a strong secret key, typically `settings.SECRET_KEY` or an environment variable, in your `settings.py`. -
AuthenticationFailed: Authentication credentials were not provided. (or 'Given token not valid for any token type')
cause The `Authorization` header is malformed, the token type is incorrect (e.g., missing "Bearer "), the token is expired, or the `AUTHENTICATION_BACKENDS` is not properly configured.fixVerify the `Authorization: Bearer <token>` header format. Check token expiration. Ensure `AUTHENTICATION_BACKENDS` in `settings.py` includes `'ninja_jwt.authentication.JWTAuthBackend'`. -
AttributeError: 'WSGIRequest' object has no attribute 'user' (within a protected endpoint)
cause The user object is not being attached to the request, usually because `JWTAuth()` is not correctly applied to the API endpoint or the `AUTHENTICATION_BACKENDS` configuration is incomplete.fixEnsure `auth=JWTAuth()` is correctly applied to your `DjangoNinja` API endpoint. Verify that `AUTHENTICATION_BACKENDS` in `settings.py` includes `'ninja_jwt.authentication.JWTAuthBackend'`. -
ModuleNotFoundError: No module named 'ninja_jwt' OR ImportError: cannot import name 'AuthRouter' from 'ninja_jwt.views'
cause The `django-ninja-jwt` library is not installed, or `ninja_jwt` is missing from `INSTALLED_APPS`, or the import path for a symbol is incorrect.fixRun `pip install django-ninja-jwt`. Verify that `'ninja_jwt'` is in your `INSTALLED_APPS` list in `settings.py`. Double-check import statements: `from ninja_jwt.views import AuthRouter` and `from ninja_jwt.authentication import JWTAuth`.
Warnings
- breaking Django Ninja JWT migrated its internal settings handling to Pydantic v2 in version `5.4.2`. If your project uses custom settings classes or older Pydantic versions that conflict, you may encounter validation errors related to the settings schema.
- gotcha For security and proper token signing, the `SIGNING_KEY` within the `SIMPLE_JWT` settings must be set to a strong, unique secret key. By default, it often falls back to `settings.SECRET_KEY`, but explicitly setting it (or ensuring `SECRET_KEY` is robust) is critical. Leaving it unset or weak leads to severe security vulnerabilities.
- gotcha If `django-ninja-jwt` fails to authenticate users even with correct tokens, a common cause is missing `ninja_jwt.authentication.JWTAuthBackend` from your `AUTHENTICATION_BACKENDS` list in `settings.py`. Django's default `ModelBackend` handles username/password, but the JWT backend is essential for token verification.
Install
-
pip install django-ninja-jwt
Imports
- JWTAuth
from ninja_jwt.authentication import JWTAuth
- AuthRouter
from ninja_jwt.views import AuthRouter
- AccessToken
from rest_framework_simplejwt.tokens import AccessToken
from ninja_jwt.tokens import AccessToken
Quickstart
import os
from datetime import timedelta
# --- In your Django project's settings.py ---
SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY', 'your-very-secret-key-for-development') # IMPORTANT: Use a strong key in production
INSTALLED_APPS = [
# ... other apps
"django.contrib.auth",
"django.contrib.contenttypes",
"ninja", # Add django-ninja
"ninja_jwt", # Add this
# ...
]
# Configure JWT settings (mimics djangorestframework-simplejwt settings)
SIMPLE_JWT = {
"ACCESS_TOKEN_LIFETIME": timedelta(minutes=5), # Short lifetime for access tokens
"REFRESH_TOKEN_LIFETIME": timedelta(days=1), # Longer lifetime for refresh tokens
"ROTATE_REFRESH_TOKENS": False,
"BLACKLIST_AFTER_ROTATION": False,
"UPDATE_LAST_LOGIN": False,
"ALGORITHM": "HS256",
"SIGNING_KEY": SECRET_KEY, # Crucial: use a strong, unique secret key here!
"VERIFYING_KEY": None,
"AUDIENCE": None,
"ISSUER": None,
"AUTH_HEADER_TYPES": ("Bearer",),
"AUTH_TOKEN_CLASSES": ("ninja_jwt.tokens.AccessToken",),
"TOKEN_TYPE_CLAIM": "token_type",
"JTI_CLAIM": "jti",
}
AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.ModelBackend', # For default Django user auth
'ninja_jwt.authentication.JWTAuthBackend', # Important for token authentication
]
# --- In your_project/urls.py (main project urls) ---
from django.contrib import admin
from django.urls import path
from ninja import NinjaAPI
from ninja_jwt.views import AuthRouter
from ninja_jwt.authentication import JWTAuth
# Create your NinjaAPI instance
api = NinjaAPI(
version="1.0.0",
title="My Django Ninja JWT API"
)
# Add the JWT authentication routes (e.g., /api/auth/token, /api/auth/token/refresh)
api.add_router("auth/", AuthRouter())
# Example protected endpoint
@api.get("/hello", auth=JWTAuth()) # Use JWTAuth to protect this endpoint
def protected_hello(request):
return {"message": f"Hello, {request.user.username}! You are authenticated."}
urlpatterns = [
path('admin/', admin.site.urls),
path("api/", api.urls), # Mount your Ninja API
]
# To run this example:
# 1. Ensure Django and django-ninja-jwt are installed.
# 2. Add 'ninja' and 'ninja_jwt' to INSTALLED_APPS in settings.py.
# 3. Configure SIMPLE_JWT and AUTHENTICATION_BACKENDS as shown.
# 4. Run `python manage.py makemigrations` and `python manage.py migrate`.
# 5. Create a superuser: `python manage.py createsuperuser`.
# 6. Run the development server: `python manage.py runserver`.
# 7. Test:
# - POST to /api/auth/token/ with {"username": "youruser", "password": "yourpassword"} to get tokens.
# - GET to /api/hello/ with 'Authorization: Bearer <your_access_token>' header.