API BOLA and IDOR: Authorization Testing Guide
API BOLA authorization testing verifies that every object read, update, and deletion enforces the caller, action, tenant, relationship, and resource policy.
Separate authentication from object authorization
API BOLA authorization testing asks whether this authenticated principal may perform this action on this specific object in this tenant and state. Changing /invoices/81 to /invoices/82 must not expose another customer’s record.
OWASP API1:2023 BOLA requires an object-level check in every function that uses a client-supplied identifier. Sequential IDs, UUIDs, IDs in JSON bodies, and nested GraphQL nodes all need the same decision. Learn the distinction in authentication, authorization, and sessions.
Inventory every endpoint that accepts an object reference
Enumerate REST paths, query parameters, request bodies, batch operations, file references, GraphQL IDs, asynchronous jobs, exports, and webhook authorization. For each, record principal type, tenant source, object type, actions, policy function, and data-store query.
Centralize policy where practical, but verify enforcement at the object-fetch boundary. A repository query constrained by both object ID and authorized tenant is safer than fetching globally and checking later.
Test positive, negative, cross-tenant, and stale-state cases
Create two tenants, several roles, owned and unowned objects, deleted records, shared resources, and parent-child relationships. For every action, keep one allowed test and multiple denied tests: another user, another tenant, wrong role, altered parent, replayed link, and changed HTTP method.
Assert status, response body, side effects, audit event, and unchanged storage. A 404 can conceal existence while still recording an authorization denial. Add these as boundary and regression tests, not one-time penetration checks.
Log policy decisions without leaking object data
Record request ID, principal and tenant IDs, route template, action, object type, keyed object fingerprint, policy name and version, decision, reason code, data-store result count, status, and latency. Do not log raw tokens or sensitive object bodies.
Detect cross-tenant attempts, one principal cycling through many object IDs, repeated denials followed by success, bulk enumeration, and authorization decisions missing a policy version. Rate limiting reduces automation but never replaces authorization.
Contain exposure, repair policy, and assess every affected object
Disable the vulnerable operation or add a server-side policy guard, revoke abused sessions, preserve request and decision logs, and identify the first exploitable release. Enumerate accessed, modified, or deleted objects from authoritative logs; do not estimate impact from a single reported example.
Correct the shared authorization path, add regression cases for every affected route, restore altered data, notify owners under the applicable process, and monitor for continued enumeration. Validate in staging with synthetic tenants before deployment.
Prove one object family is isolated end to end
Next step: choose one sensitive object such as invoices. Map every route and background job, build the role-and-tenant matrix, implement negative tests, inspect decision telemetry, and confirm denial leaves no side effect.
Use synthetic accounts and records for testing. Never probe another customer’s live objects without explicit authorization.
Frequently asked questions
Do UUID object identifiers prevent BOLA?
No. Unpredictable identifiers reduce guessing but do not authorize access. The server must evaluate policy for every object and action.
Is BOLA an authentication failure?
Usually not. The caller can be correctly authenticated and still access another user or tenant object because object authorization is missing.