Authentication¶
Keysmith validates a raw token string and attaches the result to the request. One function - authenticate_token - does all the work. Middleware and DRF are thin wrappers around it.
The validation pipeline¶
Header / query param
│
▼
Parse + CRC check ──── InvalidToken (malformed)
│
▼
Lookup by prefix ───── InvalidToken (not found)
│
▼
Lifecycle checks ───── RevokedToken / ExpiredToken
│
▼
Hash verify ────────── InvalidToken (wrong secret)
│
▼
Update last_used_at
│
▼
Return Token instance
Steps run inside a database transaction with select_for_update on the token row.
Where tokens are read from¶
By default, clients send:
Django exposes this as request.META["HTTP_X_KEYSMITH_TOKEN"].
| Setting | Default | Effect |
|---|---|---|
HEADER_NAME |
HTTP_X_KEYSMITH_TOKEN |
Which META key to read |
ALLOW_QUERY_PARAM |
False |
Also accept ?keysmith_token=… |
QUERY_PARAM_NAME |
keysmith_token |
Query parameter name |
Warning
Query-string tokens appear in access logs and browser history. Keep ALLOW_QUERY_PARAM disabled in production unless you have no alternative.
Integration points¶
Middleware (Django views)¶
Runs on every request. Sets three attributes:
request.keysmith_token # Token or None
request.keysmith_user # token.user or None
request.keysmith_auth_error # TokenAuthError subclass or None
Middleware never returns 401. Views enforce authentication with @keysmith_required.
After the response, middleware writes auth_success or auth_failed audit events - but only for views decorated with @keysmith_required.
DRF authentication class¶
KeysmithAuthentication plugs into DRF's auth flow:
request.auth→ theTokeninstancerequest.user→token.user, or DRF's unauthenticated user placeholder when no user is linked
Missing token → returns None (DRF continues to other auth classes).
TokenAuthError → raises AuthenticationFailed with the configured invalid_token message.
When both middleware and DRF are active, DRF sets _keysmith_skip_middleware_audit to prevent duplicate audit rows.
Exceptions¶
TokenAuthError
├── InvalidToken malformed, missing, unknown prefix, hash mismatch
├── RevokedToken revoked=True or purged=True
└── ExpiredToken past expires_at
Use these for internal logging. External clients should always see a generic error - see Security.
Direct usage¶
from keysmith.auth.base import authenticate_token
from keysmith.auth.exceptions import InvalidToken, ExpiredToken, RevokedToken
try:
token = authenticate_token(raw_token)
except (InvalidToken, ExpiredToken, RevokedToken) as exc:
log_internally(exc)
return generic_401()
Rate limiting¶
RATE_LIMIT_HOOK runs in middleware before authenticate_token:
DRF_THROTTLE_HOOK runs after successful DRF authentication. It can raise DRF's Throttled exception.
See also: Django integration · DRF integration · Authentication reference