HIGH integrity failuresdjangobearer tokens

Integrity Failures in Django with Bearer Tokens

Integrity Failures in Django with Bearer Tokens — how this specific combination creates or exposes the vulnerability

An integrity failure occurs when a system allows unauthorized modification of data or behavior. In Django, using Bearer Tokens for API authentication can expose integrity risks when token validation is incomplete or when tokens are accepted without sufficient checks. If a Django API endpoint relies solely on the presence of a Bearer Token and does not enforce scope-based authorization or strict origin validation, an attacker may be able to alter requests in ways the server implicitly trusts.

Consider a typical pattern where a client sends Authorization: Bearer <token> and the server uses Django REST Framework’s TokenAuthentication or a custom JWT handler without verifying token integrity beyond existence. Without validating token bindings, scopes, or audience claims, an attacker who obtains or guesses a token might replay it to modify resources they should not own. This can lead to BOLA (Broken Object Level Authorization) when object ownership is not rechecked server-side and the token is treated as proof of privilege.

Django APIs that accept Bearer Tokens without verifying the token’s intended resource server (audience) or issuer (iss) can be tricked into trusting a token issued for a different service. If your Django settings include USE_SESSION_AUTHENTICATION = False and you rely on a middleware that parses Authorization headers but skips signature or claim validation, you risk integrity failures where an attacker can tamper with request parameters or IDs.

Additionally, if rate limiting and logging are not aligned with token identity, malicious actors can exploit weak per-token tracking to probe for IDOR patterns. For example, an endpoint like /api/projects/{project_id}/ that uses Bearer Tokens for authentication but does not enforce project-level ownership checks may allow token reuse across users if the token lacks user-specific claims. This cross-user acceptance can let one user act on another user’s projects when the token is accepted without validating project membership.

In secure designs, integrity checks must include verifying token signatures, validating claims such as scope and aud, and enforcing strict object ownership checks in every handler. MiddleBrick’s LLM/AI Security and Property Authorization checks specifically test for missing claim validation and excessive agency in API behaviors, which are common root causes of integrity failures with Bearer Tokens.

Bearer Tokens-Specific Remediation in Django — concrete code fixes

To remediate integrity risks when using Bearer Tokens in Django, enforce strict validation of token content and re-check object ownership on every request. Below are concrete, realistic code examples that demonstrate how to implement these protections.

1. Use a custom authentication class with claim validation

If you use JWT Bearer tokens, avoid relying on third-party libraries that skip audience or issuer checks. Implement a custom authentication class in Django REST Framework that validates standard claims and scopes:

import jwt
from django.conf import settings
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed, PermissionDenied
from rest_framework.request import Request

class BearerTokenJWTAuthentication(BaseAuthentication):
    keyword = 'Bearer'

    def authenticate(self, request):
        auth_header = request.META.get('HTTP_AUTHORIZATION')
        if not auth_header or not auth_header.startswith(self.keyword + ' '):
            return None

        token = auth_header.split(self.keyword + ' ')[1]
        try:
            payload = jwt.decode(
                token,
                settings.SECRET_KEY,  # or your public key
                algorithms=['HS256'],
                audience='myapi.example.com',
                issuer='auth.myapp.com',
            )
        except jwt.ExpiredSignatureError:
            raise AuthenticationFailed('Token expired')
        except jwt.InvalidAudienceError:
            raise AuthenticationFailed('Invalid audience')
        except jwt.InvalidIssuerError:
            raise AuthenticationFailed('Invalid issuer')
        except jwt.InvalidTokenError:
            raise AuthenticationFailed('Invalid token')

        # Ensure required scopes are present
        if 'scope' in payload and not any(s in payload['scope'].split() for s in ['projects:read', 'projects:write']):
            raise PermissionDenied('Insufficient scope')

        return (payload, token)

2. Enforce object ownership in views

Even with a validated token, always re-check object ownership. Do not trust token claims alone to enforce BOLA protections:

from rest_framework import generics
from .models import Project
from .serializers import ProjectSerializer

class ProjectDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Project.objects.all()
    serializer_class = ProjectSerializer

    def get_queryset(self):
        user_id = self.request.auth[0].get('sub')  # subject from validated token
        return self.queryset.filter(owned_by_id=user_id)

3. Validate token binding for sensitive operations

For state-changing methods, require token binding or nonce checks to prevent replay:

from django.utils.http import urlsafe_base64_encode
from django.utils.encoding import force_str

def validate_token_binding(request, token_payload, resource_id):
    # Example: bind token to resource hash
    binding = urlsafe_base64_encode(
        str(resource_id).encode()
    )
    if token_payload.get('bind') != binding:
        raise PermissionDenied('Token binding mismatch')

4. Use Django settings to disable unsafe defaults

Ensure session authentication is not used as a fallback when Bearer validation fails:

# settings.py
USE_SESSION_AUTHENTICATION = False
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'myapp.auth.BearerTokenJWTAuthentication',
    ],
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',
    ],
}

These patterns reduce the risk of integrity failures by ensuring Bearer Tokens are validated for audience, issuer, and scope, and by re-checking object ownership on every request. MiddleBrick’s CLI can scan your endpoints to verify that such protections are present and that tokens are not accepted without strict validation.

Frequently Asked Questions

How can I test if my Django API properly validates Bearer Token claims?
Send requests with missing, invalid, or mismatched audience/issuer claims using the middlebrick CLI: middlebrick scan . Inspect the Property Authorization and LLM/AI Security findings for missing claim validation.
Does using Bearer Tokens eliminate the need for object-level ownership checks?
No. Always enforce object-level ownership in your views. Tokens indicate identity and scope but do not replace per-request checks that the authenticated subject has permission for the specific resource.