Key-based authentication protects an API by requiring a secret key in every request, usually inside an HTTP header. Unlike browser authentication, which relies on a session cookie, this approach makes each API call carry its own proof of access. section 11.2.5
Django Ninja provides APIKeyHeader for this job. Extend it, name the header, and implement authenticate(): return the key for a match or None for failure. Pass one shared handler instance through an endpoint’s auth argument. section 11.2.5
Listing 11.12 Creating an authentication handler based on a key
# RiffMates/api_auth.py
from django.conf import settings
from ninja.security import APIKeyHeader
class APIKey(APIKeyHeader):
param_name = "X-API-KEY" #1
def authenticate(self, request, key):
if key == settings.NINJA_API_KEY: #2
return key #3
api_key = APIKey() #4
The handler reads X-API-KEY and compares it with settings.NINJA_API_KEY. A matching value authenticates the request; otherwise authentication fails. Keep the configured key appropriately cryptic rather than using an example value such as notsecure. section 11.2.5
Authentication applies where the handler is attached. A create endpoint can import api_key and declare auth=api_key, causing unauthenticated POST requests to receive Permission Denied before creating a database object. section 11.2.6
Testing an authenticated create request
A Django test supplies the header, sends JSON, and then checks the response: headers = {"X-API-KEY": settings.NINJA_API_KEY}; data = {"name": "some venue name", "description": "some venue description"}; response = self.client.post("/api/v1/bands/venue/", data, content_type="application/json", headers=headers). section 11.2.6
The Ninja documentation interface can also authorize requests interactively. Enter the header’s key once, then execute protected calls; the authorization may need to be entered again after restarting the development server. section 11.2.6

