HIGH auth bypassflaskbearer tokens

Auth Bypass in Flask with Bearer Tokens

Auth Bypass in Flask with Bearer Tokens — how this specific combination creates or exposes the vulnerability

Flask APIs that rely on Bearer tokens for authentication can permit an Auth Bypass when token validation is inconsistently enforced across endpoints or when token extraction is fragile. The vulnerability occurs when a route either skips the token-verification function, incorrectly trusts request attributes, or fails to secure the token issuance endpoint itself.

Consider a Flask app that defines a require_token decorator but applies it selectively. If an administrative route is accidentally omitted, an unauthenticated attacker can reach privileged functionality even though most endpoints require a Bearer token. Incomplete decorator coverage is a common implementation error.

from flask import Flask, request, jsonify

def require_token(f):
    def wrapper(*args, **kwargs):
        auth = request.headers.get('Authorization')
        if not auth or not auth.startswith('Bearer '):
            return jsonify({'error': 'missing or invalid token'}), 401
        token = auth.split(' ')[1]
        if token != 's3cr3t_v4lid_t0k3n':
            return jsonify({'error': 'invalid token'}), 401
        return f(*args, **kwargs)
    wrapper.__name__ = f.__name__
    return wrapper

app = Flask(__name__)

@app.route('/public')
def public():
    return jsonify({'msg': 'public endpoint'})

@app.route('/admin')
@require_token
def admin():
    return jsonify({'msg': 'admin endpoint'})

if __name__ == '__main__':
    app.run()

In the example, the /admin route is protected, but if a developer later adds a new privileged route and forgets to add @require_token, the Auth Bypass exists. Additionally, if the token validation logic resides in middleware that does not run for all paths (for example, due to route ordering or blueprint configuration), some routes may be processed without verification.

Another realistic issue stems from how the token is compared. A naive string comparison can be vulnerable to certain timing-related side channels or misconfiguration. More importantly, if the token is expected in a specific format (e.g., a JWT) but the app only checks a static string, an attacker does not need to crack or steal a real token; they only need to know the exact string the server checks, which can be discovered through source code review or misconfigured logging.

Flask apps that parse the Authorization header inconsistently also risk bypass. For example, if a proxy or load balancer terminates TLS and forwards requests as HTTP, the header may be transformed or stripped. If the app falls back to alternative sources (e.g., a custom header) without strict validation, an attacker can supply a spoofed header that bypasses the Bearer check.

Auth Bypass in this context is not always a missing decorator. It can be a logic flaw where the token is accepted from an unexpected location, or where the validation result is not enforced uniformly. Because middleBrick scans test the unauthenticated attack surface, it can flag routes that lack required authentication checks and highlight inconsistencies in how Bearer tokens are enforced across the API surface.

Bearer Tokens-Specific Remediation in Flask — concrete code fixes

Remediation centers on consistent, centralized token validation and strict handling of the Authorization header. Implement a single, reusable decorator that every protected route uses, and ensure the decorator is applied before any route logic executes.

Use constant-time comparisons for token validation to reduce timing side-channel risks, and prefer structured tokens such as JWTs with proper signature verification over static strings. Below is a hardened example using PyJWT for token verification and a centralized decorator.

import jwt
from flask import Flask, request, jsonify
from functools import wraps
from datetime import datetime, timezone

app = Flask(__name__)
SECRET_KEY = 'your_strong_secret_here'
ALGORITHM = 'HS256'

def require_token(f):
    @wraps(f)
    def wrapper(*args, **kwargs):
        auth = request.headers.get('Authorization')
        if not auth:
            return jsonify({'error': 'authorization header missing'}), 401
        parts = auth.split()
        if len(parts) != 2 or parts[0].lower() != 'bearer':
            return jsonify({'error': 'invalid authorization format, expected Bearer token'}), 401
        token = parts[1]
        try:
            payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
            # optionally enforce exp, iss, or scope checks here
            request.token_payload = payload
        except jwt.ExpiredSignatureError:
            return jsonify({'error': 'token expired'}), 401
        except jwt.InvalidTokenError:
            return jsonify({'error': 'invalid token'}), 401
        return f(*args, **kwargs)
    return wrapper

@app.route('/public')
def public():
    return jsonify({'msg': 'public endpoint'})

@app.route('/admin')
@require_token
def admin():
    return jsonify({'msg': 'admin endpoint', 'user': request.token_payload.get('sub')})

if __name__ == '__main__':
    app.run()

Key remediation practices:

  • Apply the @require_token decorator to every route that requires authentication; avoid omissions by reviewing all routes during code reviews.
  • Validate the Authorization header format strictly: it must contain exactly two parts, with the first part being Bearer (case-insensitive).
  • Use a library such as PyJWT to decode and verify signed tokens. Verify the signature, and where relevant check claims like exp (expiration) and iss (issuer).
  • Avoid static string comparisons for production tokens; use cryptographic verification so that token compromise on one client does not trivially compromise the API.
  • If your architecture uses a proxy, ensure the Authorization header is preserved end-to-end and not stripped or rewritten in a way that bypasses validation.

These changes ensure that authentication is enforced consistently, reducing the likelihood of an Auth Bypass. middleBrick’s unauthenticated scans can verify whether protected routes still lack proper token checks and whether token validation logic is reachable without credentials.

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 can I verify my Flask Bearer token protection is consistent across all routes?
Use a centralized decorator for every protected route and audit your codebase to ensure no endpoint is missing the decorator. middleBrick can scan the unauthenticated attack surface and report routes that lack required authentication checks, helping you detect missing or inconsistent enforcement.
Is a static Bearer token acceptable for testing environments?
For short-lived test environments, a static token can simplify setup, but it should never be used in production. Prefer signed JWTs with expiration and scope checks, and rotate secrets regularly. middleBrick’s LLM/AI Security checks do not apply to static token usage but its auth checks can highlight weak authentication patterns.