HIGH time of check time of useflaskbearer tokens

Time Of Check Time Of Use in Flask with Bearer Tokens

Time Of Check Time Of Use in Flask with Bearer Tokens — how this specific combination creates or exposes the vulnerability

Time Of Check Time Of Use (TOCTOU) is a class of race condition where a decision is made based on the state of a resource at one point in time, but the resource changes before the action is completed. In Flask applications that use Bearer Tokens for authentication, TOCTOU can occur when authorization checks rely on token validity or claims that may become invalid between the check and the use of the protected resource.

Consider a Flask route that validates a Bearer Token, checks a scope or role in the token, and then performs an operation such as reading or modifying a resource. If the token is revoked, expired, or has its permissions changed after the check but before the use, the request may still proceed with outdated authorization. This is particularly relevant when token validation involves a network call or a cached lookup that is not re-evaluated immediately before the sensitive action.

An example scenario: a Flask endpoint verifies a Bearer Token’s scopes to decide whether a user can delete a resource. The token is validated and scopes are read at the start of the request. Later, the endpoint loads the resource and proceeds to delete it. If an attacker can cause the token’s state to change between scope validation and deletion (for example, by revoking the token or escalating privileges in the identity provider), the authorization decision becomes stale. The deletion proceeds because the check passed earlier, even though the token should no longer be allowed to perform that action.

Another TOCTOU pattern arises when token introspection or claims are cached for performance. If the cache is not invalidated or refreshed atomically with the action, a token that was valid at check time may be used after it should have been invalidated. This can allow unauthorized operations on behalf of a user whose token has been revoked or whose permissions have been downgraded.

In Flask, a typical vulnerable pattern looks like verifying the token and extracting claims early in a request, storing them in g or a local variable, and then using those claims later to authorize an operation without re-checking the token state. Because the token is not re-validated immediately before the sensitive operation, there is a window where the token’s validity or permissions may have changed.

To summarize, the combination of Flask routing, Bearer Token authentication, and non-atomic authorization checks creates TOCTOU when the state used for authorization is not re-validated immediately before the action. Attackers can exploit this window to perform actions with outdated or incorrect authorization, leading to unauthorized access or data manipulation.

Bearer Tokens-Specific Remediation in Flask — concrete code fixes

Remediation focuses on ensuring authorization decisions are made as close as possible to the action and that token state is re-validated or that operations are designed to be idempotent and safe even if a token changes. Below are concrete patterns and code examples to address TOCTOU in Flask with Bearer Tokens.

1. Avoid long-lived authorization state derived from the token. Instead of extracting claims once and reusing them, re-validate or re-check critical authorization decisions immediately before sensitive operations. For example, if a deletion requires a specific scope, verify the scope again within the same request just before performing the deletion.

from flask import Flask, request, g, abort
import jwt

app = Flask(__name__)
SECRET_KEY = 'your-secret'

def get_current_token():
    auth = request.headers.get('Authorization')
    if not auth or not auth.startswith('Bearer '):
        abort(401, 'Missing or invalid token')
    return auth.split(' ')[1]

def validate_token(token):
    # Decode and verify signature/expiry; in production use a proper key/algorithm
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=['HS256'])
        return payload
    except jwt.ExpiredSignatureError:
        abort(401, 'Token expired')
    except jwt.InvalidTokenError:
        abort(401, 'Invalid token')

@app.before_request
def load_current_user():
    token = get_current_token()
    g.user = validate_token(token)

@app.route('/resource/', methods=['DELETE'])
def delete_resource(id):
    token = get_current_token()
    user = validate_token(token)  # re-validate immediately before the action
    if 'delete:resource' not in user.get('scopes', []):
        abort(403, 'Insufficient scope')
    # Perform deletion using id, ensuring user has access to this specific resource
    if not user_can_delete_resource(user, id):
        abort(403, 'Not allowed to delete this resource')
    # actual deletion logic here
    return '', 204

def user_can_delete_resource(user, resource_id):
    # Implement your own ownership or permission check here
    return True

2. Use per-request token validation for sensitive operations rather than relying on values stored in g across multiple middleware or route steps. By calling validate_token again within the route, you ensure the latest token state is considered. This reduces the window where a changed token state can lead to incorrect authorization.

3. When possible, make operations idempotent and safe so that using a slightly stale token is less risky. For deletions, require additional confirmation or a second factor, and design endpoints to check resource ownership or required permissions at the data layer, not only at the route level.

4. If you cache token introspection results, ensure cache invalidation is tightly coupled with the authorization check or bypass the cache for critical operations. Prefer short-lived tokens and refresh mechanisms so that re-validation is inexpensive and reliable.

5. Consider using an access token pattern where a short-lived access token is used for authorization checks and a separate refresh token is used to obtain new access tokens. This limits the impact of a token change and reduces the window where a stale authorization decision could be used.

These practices help mitigate TOCTOU by ensuring that authorization decisions for Bearer Token-protected routes in Flask are based on current token state immediately before sensitive actions, rather than on earlier, potentially outdated information.

Frequently Asked Questions

How does middleBrick relate to detecting authorization issues like TOCTOU?
middleBrick scans API endpoints and returns security findings, including authorization issues such as BOLA/IDOR and privilege escalation. It provides prioritized findings with severity and remediation guidance, but it does not fix or block issues; it helps you identify and address problems like TOCTOU in your API.
Can the free plan be used to scan APIs behind authentication?
middleBrick scans the unauthenticated attack surface by default. To test authenticated flows, you would need to provide appropriate authentication context or use a plan that supports authenticated scanning, as described in the Pro and Enterprise tiers.