Integrity Failures in Flask with Bearer Tokens
Integrity Failures in Flask with Bearer Tokens
Integrity failures occur when an API fails to detect tampering with requests or tokens, allowing an attacker to modify data, escalate privileges, or bypass authorization. In Flask APIs that rely on Bearer Tokens, these failures often arise from inconsistent validation, lack of signature verification, or improper scope checks. When tokens are accepted without validating their integrity, an attacker can manipulate claims (such as roles or permissions), substitute tokens, or forge credentials that the server treats as valid.
Consider a Flask route that extracts a Bearer Token from the Authorization header and uses it without verifying the token’s signature or claims. If the application trusts the token payload without ensuring it was issued by a trusted identity provider, an attacker can change the role claim from user to admin and gain elevated access. This is an integrity failure because the server does not cryptographically verify the token origin or binding.
Another common pattern involves using opaque tokens without checking revocation status or scope. For example, a token issued for read-only access might be modified client-side to include write permissions if the server does not revalidate token scope against an authorization server or a local policy store. This exposes the API to BOLA/IDOR and privilege escalation via tampered tokens.
Middleware that parses tokens but skips signature validation increases the risk of integrity failures. Without verifying the token’s digital signature (e.g., via JWKs for RSA or HMAC secrets for symmetric tokens), an attacker can inject arbitrary values into the token payload. This is especially dangerous when the Flask app uses the token to make authorization decisions without additional checks.
Flask applications that integrate with OAuth2 providers must also guard against token substitution across endpoints. If a Bearer Token is accepted for multiple services without verifying the intended audience (aud) claim, an attacker can reuse a token from one service on another. This violates integrity and can lead to unauthorized data access or actions across microservices.
Using middleBrick’s LLM/AI Security checks helps detect system prompt leakage and prompt injection risks that could expose token handling logic. Its unauthenticated LLM endpoint detection can identify endpoints that accept tokens without proper validation, complementing the 12 security checks that include Authentication, BOLA/IDOR, and Input Validation.
Bearer Tokens-Specific Remediation in Flask
Remediation focuses on cryptographically verifying tokens, validating claims, and enforcing scope-based authorization. Always verify the token signature using the appropriate key or secret, and validate standard claims such as iss, aud, exp, and nbf. Enforce scope checks for each endpoint and avoid trusting token payloads without verification.
Use a well-maintained library such as PyJWT to decode and verify tokens. Below is a Flask route example that validates a Bearer Token using a public key for RSA signatures:
from flask import Flask, request, jsonify
import jwt
from jwt import PyJWKClient
app = Flask(__name__)
JWKS_URL = "https://auth.example.com/.well-known/jwks.json"
AUDIENCE = "https://api.example.com"
ISSUER = "https://auth.example.com/"
def get_jwks_manager():
return PyJWKClient(JWKS_URL)
@app.route("/secure-endpoint")
def secure_endpoint():
auth_header = request.headers.get("Authorization")
if not auth_header or not auth_header.startswith("Bearer "):
return jsonify({"error": "unauthorized"}), 401
token = auth_header.split(" ")[1]
try:
jwks_client = get_jwks_manager()
signing_key = jwks_client.get_signing_key_from_jwt(token)
decoded = jwt.decode(
token,
key=signing_key.key,
algorithms=["RS256"],
audience=AUDIENCE,
issuer=ISSUER,
options={"require": ["exp", "iss", "aud"]},
)
# Enforce scope-based checks
if "read:data" not in decoded.get("scope", "").split():
return jsonify({"error": "insufficient_scope"}), 403
return jsonify({"data": "secure", "user": decoded["sub"]})
except jwt.ExpiredSignatureError:
return jsonify({"error": "token_expired"}), 401
except jwt.InvalidTokenError:
return jsonify({"error": "invalid_token"}), 401
For symmetric secrets, verify using HMAC:
import jwt
from flask import request, jsonify
SECRET_KEY = "your-256-bit-secret"
def verify_bearer_token(token):
try:
decoded = jwt.decode(
token,
SECRET_KEY,
algorithms=["HS256"],
audience="https://api.example.com",
issuer="https://auth.example.com/",
options={"require": ["exp", "iss", "aud"]},
)
return decoded
except jwt.InvalidTokenError:
return None
@app.route("/profile")
def profile():
auth = request.headers.get("Authorization")
if not auth or not auth.startswith("Bearer "):
return jsonify({"error": "missing_token"}), 401
token = auth.split(" ")[1]
payload = verify_bearer_token(token)
if not payload:
return jsonify({"error": "invalid_token"}), 401
return jsonify({"user_id": payload["sub"], "role": payload.get("role")})
Always validate token binding by checking the aud claim to prevent cross-service token reuse. Enforce scope and role checks at the endpoint level rather than relying on token decoding alone. Use short token lifetimes and refresh tokens where applicable, and consider integrating introspection endpoints for opaque tokens.
middleBrick’s Dashboard and CLI can be used to track scans over time and integrate API security checks into your workflow. Its GitHub Action helps enforce security gates in CI/CD, while the MCP Server allows scanning directly from AI coding assistants.