HIGH jwt misconfigurationdjangodynamodb

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-jsonwebtoken or a similar library is used without enforcing HTTPS and strict token validation, tokens can be intercepted or accepted over insecure channels. For example, omitting verify=True and not setting JWT_VERIFY_EXPIRATION = True allows 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_id without 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 where PK = USER#<user_id> and SK = 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 IDNameSeverity
CWE-287Improper Authentication CRITICAL
CWE-306Missing Authentication for Critical Function CRITICAL
CWE-307Brute Force HIGH
CWE-308Single-Factor Authentication MEDIUM
CWE-309Use of Password System for Primary Authentication MEDIUM
CWE-347Improper Verification of Cryptographic Signature HIGH
CWE-384Session Fixation HIGH
CWE-521Weak Password Requirements MEDIUM
CWE-613Insufficient Session Expiration MEDIUM
CWE-640Weak Password Recovery HIGH

Frequently Asked Questions

How does DynamoDB key design affect JWT security in Django?
Using a low-cardinality partition key or predictable sort keys can enable BOLA/IDOR: attackers who guess token IDs can read or overwrite other users' token records. Use a high-entropy token_id as a sort key and enforce ownership checks on every read.
Can middleBrick scans help detect JWT misconfigurations with DynamoDB-backed APIs?
Yes. middleBrick runs 12 parallel security checks including Authentication, BOLA/IDOR, and Input Validation, and it maps findings to frameworks like OWASP API Top 10. Its LLM/AI Security checks also detect unauthenticated LLM endpoints that could be chained with token handling issues.