Jwt Misconfiguration in Django with Hmac Signatures
Jwt Misconfiguration in Django with Hmac Signatures — how this specific combination creates or exposes the vulnerability
JSON Web Tokens (JWT) are widely used for stateless authentication. When using HMAC signatures in Django, the security of the token depends on a strong shared secret and strict validation. Misconfiguration typically occurs when the secret is weak, hardcoded in source code, or accidentally exposed, or when the algorithm is not explicitly enforced during verification.
Consider this insecure example where a developer uses PyJWT without specifying algorithms and with a predictable secret:
import jwt
SECRET = "12345" # weak and exposed
def create_token(user_id):
return jwt.encode({"sub": user_id, "role": "user"}, SECRET, algorithm="HS256")
def decode_token(token):
# Missing algorithms parameter; vulnerable to algorithm confusion
return jwt.decode(token, SECRET, options={"verify_signature": False})
By disabling signature verification (verify_signature: False) or omitting the algorithms argument, the application can be tricked into accepting an unsigned token or a token signed with a different algorithm (e.g., none or RS256) if the library defaults are exploited. This is a classic JWT misconfiguration that maps to the OWASP API Security Top 10 category of Broken Object Level Authorization (BOLA/IDOR) and Authentication flaws.
Another common issue is logging or exposing the secret via error messages or debug endpoints. If an attacker can cause the application to reveal the secret—through information leakage or SSRF that reaches internal configuration—the integrity of all HMAC-signed tokens is compromised. middleBrick scans for such information exposure as part of its Data Exposure and Authentication checks, flagging weak secrets and unsafe token handling.
Additionally, missing audience (aud) and issuer (iss) claims allows token substitution across services. Without validating these claims, an attacker could reuse a token intended for one service on another service within the same ecosystem, escalating impact via BOLA/IDOR. middleBrick’s OpenAPI/Swagger analysis cross-references declared security schemes with runtime behavior to detect such gaps.
Insecure storage of the HMAC secret in environment variables that are inadvertently logged or included in client-side code also creates risk. middleBrick’s LLM/AI Security checks specifically look for secret leakage patterns and unsafe handling of tokens in outputs, ensuring that misconfigured token handling is surfaced with severity and remediation guidance.
Hmac Signatures-Specific Remediation in Django — concrete code fixes
To secure JWT handling with HMAC in Django, always specify allowed algorithms, validate all standard claims, and protect the secret. Use a strong, randomly generated secret stored securely (e.g., via Django settings from a secrets manager) and avoid disabling signature verification.
Here is a secure implementation example using PyJWT:
import jwt
from datetime import datetime, timedelta, timezone
from django.conf import settings
# Strong secret sourced from Django settings; keep it out of source code
SECRET_KEY = getattr(settings, "JWT_HMAC_SECRET", "")
ALGORITHM = "HS256"
AUDIENCE = "myapi.example.com"
ISSUER = "django-app.example.com"
def create_token(user_id: str) -> str:
now = datetime.now(timezone.utc)
payload = {
"sub": user_id,
"role": "user",
"iat": now,
"exp": now + timedelta(hours=1),
"aud": AUDIENCE,
"iss": ISSUER,
}
return jwt.encode(payload, SECRET_KEY, algorithm=ALGORITHM)
def decode_token(token: str) -> dict:
return jwt.decode(
token,
SECRET_KEY,
algorithms=[ALGORITHM],
audience=AUDIENCE,
issuer=ISSUER,
options={"require": ["exp", "iat", "aud", "iss"]},
)
Key points in the remediation:
- Always pass
algorithms=["HS256"]tojwt.decodeto prevent algorithm confusion attacks. - Validate
audienceandissuerto ensure tokens are intended for your service. - Set short expiration times and use
iat(issued at) to detect replay windows. - Never set
verify_signature=Falseor omit the algorithms list. - Rotate the HMAC secret periodically and monitor for anomalies; middleBrick’s continuous monitoring in the Pro plan can alert on score drops related to authentication changes.
If you use Django REST Framework, integrate the token validation into permissions rather than views directly. For example:
from rest_framework.permissions import BasePermission
import jwt
class JWTAuthenticationPermission(BasePermission):
def has_permission(self, request, view):
auth = request.headers.get("Authorization")
if not auth or not auth.startswith("Bearer "):
return False
token = auth.split(" ")[1]
try:
jwt.decode(
token,
settings.JWT_HMAC_SECRET,
algorithms=["HS256"],
audience=settings.JWT_AUDIENCE,
issuer=settings.JWT_ISSUER,
)
return True
except jwt.PyJWTError:
return False
middleBrick’s GitHub Action can be added to CI/CD pipelines to fail builds if a scan detects weak secrets or missing algorithm constraints. The CLI provides JSON output for scripting: middlebrick scan <url>. For AI-assisted development, the MCP Server lets you scan APIs directly from your coding assistant, catching misconfigurations before deployment.
Related CWEs: authentication
| CWE ID | Name | Severity |
|---|---|---|
| CWE-287 | Improper Authentication | CRITICAL |
| CWE-306 | Missing Authentication for Critical Function | CRITICAL |
| CWE-307 | Brute Force | HIGH |
| CWE-308 | Single-Factor Authentication | MEDIUM |
| CWE-309 | Use of Password System for Primary Authentication | MEDIUM |
| CWE-347 | Improper Verification of Cryptographic Signature | HIGH |
| CWE-384 | Session Fixation | HIGH |
| CWE-521 | Weak Password Requirements | MEDIUM |
| CWE-613 | Insufficient Session Expiration | MEDIUM |
| CWE-640 | Weak Password Recovery | HIGH |