Jwt Misconfiguration in Django with Dynamodb
Jwt Misconfiguration in Django with Dynamodb — how this specific combination creates or exposes the vulnerability
JWT misconfiguration in a Django application that uses DynamoDB as a data store can expose authentication bypass, token tampering, or privilege escalation risks. Several factors specific to this stack contribute to the vulnerability.
- Django settings and JWT library choices: If
django-jsonwebtokenor a similar library is used without enforcingHTTPSand strict token validation, tokens can be intercepted or accepted over insecure channels. For example, omittingverify=Trueand not settingJWT_VERIFY_EXPIRATION = Trueallows expired tokens to be accepted. - DynamoDB data model and token storage: When tokens or session references are stored in DynamoDB, weak partition key design can lead to unintended data access. A common misconfiguration is using a static or low-cardinality partition key (e.g., storing tokens under a single
user_idwithout a proper sort key), which can enable BOLA/IDOR if an attacker iterates through sort keys or guesses identifiers. For instance, storing tokens in a table wherePK = USER#<user_id>andSK = TOKEN#<token_id>without proper authorization checks on access can expose token records to other users who guess or iterate IDs. - Token claims and DynamoDB conditional writes: Failing to validate claims such as
iss(issuer),aud(audience), and custom scopes against DynamoDB-stored app state can lead to token reuse across services. If a token issued for one API audience is accepted by another, or if revocation is not checked against DynamoDB, an attacker can reuse a stolen token. - Insecure signing keys and DynamoDB access patterns: Using weak signing keys or storing secrets in environment variables that are inadvertently exposed (e.g., through logs or IAM policies) can allow token forgery. If DynamoDB streams or backups are not properly restricted, leaked token data can aid horizontal privilege escalation across user accounts.
- Unauthenticated LLM endpoints and JWT handling: If an endpoint exposed for LLM interactions does not validate JWTs and relies on permissive CORS or misconfigured middleware, an attacker can chain this with DynamoDB resource handling to infer or manipulate data. middleBrick’s LLM/AI Security checks specifically detect unauthenticated LLM endpoints and system prompt leakage, which can complement API testing for this stack.
Dynamodb-Specific Remediation in Django — concrete code fixes
To secure JWT handling with DynamoDB in Django, enforce strict token validation, use strong key designs, and validate access patterns. Below are concrete, realistic code examples.
1. Configure Django JWT settings with DynamoDB-aware validation
Ensure token expiration and HTTPS verification are enforced. Example using django-jsonwebtoken:
JWT_AUTH = {
'JWT_VERIFY': True,
'JWT_VERIFY_EXPIRATION': True,
'JWT_LEEWAY': 0,
'JWT_AUDIENCE': 'your-api-audience',
'JWT_ISSUER': 'your-django-service',
'JWT_ALGORITHM': 'RS256',
'JWT_PUBLIC_KEY': open('public.key').read(),
'JWT_PRIVATE_KEY': open('private.key').read(),
}
2. Secure DynamoDB table design for token and session data
Use a composite key with a high-cardinality sort key and enforce authorization checks on reads. Example using boto3 with Django models:
import boto3
from django.conf import settings
dynamodb = boto3.resource('dynamodb', region_name=settings.AWS_REGION)
table = dynamodb.Table(settings.DYNAMODB_TOKEN_TABLE)
# Store token with user_id as partition key and a random token_id as sort key
def store_token(user_id, token_id, token_payload):
table.put_item(
Item={
'PK': f'USER#{user_id}',
'SK': f'TOKEN#{token_id}',
'payload': token_payload,
'created_at': int(time.time()),
'scopes': ['read', 'write'],
}
)
# Retrieve token with ownership check
def get_token_for_user(user_id, token_id):
response = table.get_item(
Key={
'PK': f'USER#{user_id}',
'SK': f'TOKEN#{token_id}',
}
)
return response.get('Item')
3. Validate token claims against DynamoDB state
Before processing a request, cross-check token audience and issuer with stored app metadata:
import jwt
from django.http import HttpResponseForbidden
def validate_token_claims(token):
try:
decoded = jwt.decode(
token,
open('public.key').read(),
algorithms=['RS256'],
audience='your-api-audience',
issuer='your-django-service',
)
user_id = decoded.get('sub')
# Verify token exists and is not revoked in DynamoDB
item = table.get_item(Key={'PK': f'USER#{user_id}', 'SK': f'TOKEN#{decoded["jti"]}'}).get('Item')
if not item or item.get('revoked'):
return None
return decoded
except jwt.ExpiredSignatureError:
return None
except jwt.InvalidTokenError:
return None
4. Enforce least-privilege IAM and conditional writes
Ensure the IAM role used by Django has least-privilege access to DynamoDB and use conditional writes to prevent overwriting tokens:
table.put_item(
Item={
'PK': 'USER#123',
'SK': 'TOKEN#abc',
'payload': '...',
},
ConditionExpression='attribute_not_exists(PK) AND attribute_not_exists(SK)'
)
5. Revocation and cleanup patterns
Implement token revocation by marking items in DynamoDB and use TTL for cleanup:
# Mark token as revoked
def revoke_token(user_id, token_id):
table.update_item(
Key={'PK': f'USER#{user_id}', 'SK': f'TOKEN#{token_id}'},
UpdateExpression='SET revoked = :r',
ExpressionAttributeValues={':r': True}
)
# Enable TTL on DynamoDB table for automatic expiration (set attribute 'ttl' with epoch timestamp)
By combining strict JWT validation with carefully designed DynamoDB access patterns and conditional writes, you reduce the risk of token tampering, IDOR, and unauthorized access in this stack.
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 |