Broken Object Level Authorization (BOLA) occurs when an API accepts a request for a specific object without correctly checking whether the caller is allowed to access that object. It is one of the most important authorization tests because the application may appear perfectly authenticated while still exposing another user’s data.
The core test is simple: change the object reference while keeping the authenticated identity the same. The hard part is doing this systematically across the application’s object graph.
Build an object map before attacking
Start by identifying object identifiers and relationships: user IDs, account IDs, order IDs, document IDs, project IDs, message IDs, invoice IDs, UUIDs and nested resource paths. Record which roles and tenants should be able to access each object.
A repeatable test pattern
- Authenticate as User A.
- Perform a legitimate request for an object User A owns.
- Capture the request and identify the object reference.
- Replace the reference with an object belonging to User B or another tenant.
- Compare status code, response body, side effects and secondary API calls.
- Repeat with read, update and delete operations.
Do not stop at numeric IDs
UUIDs, opaque tokens and encoded identifiers can make enumeration harder, but they do not implement authorization. If you can obtain another valid identifier through a list endpoint, notification, browser history, mobile response or predictable workflow, the authorization check still matters.
REST and GraphQL variations
REST testing often focuses on path and body parameters such as /api/orders/1234 or {"orderId":1234}. GraphQL adds another layer: object references can be embedded inside queries, mutations, variables or nested resolver arguments. Test each resolver independently because a secure parent object does not guarantee secure child-object authorization.
Interactive: expected vs. vulnerable behavior
Change the requested object
Authorization test matrix
| Operation | Same user | Other user | Other tenant |
|---|---|---|---|
| GET | Allow | Deny unless explicitly shared | Deny |
| PUT / PATCH | Allow if role permits | Deny | Deny |
| DELETE | Allow if role permits | Deny | Deny |
| Nested object | Allow if parent + child authorized | Deny | Deny |
What strong authorization looks like
Enforce authorization server-side at the point where the object is accessed. Prefer policy checks based on authenticated identity, tenant, role and object ownership. Avoid relying on hidden fields, client-side controls, object ID secrecy or UI restrictions.
For sensitive operations, log the authorization decision and test negative cases as part of automated integration testing. A regression suite should include cross-user and cross-tenant access attempts.
Further reading
OWASP’s API Security Project covers object-level authorization as a central API security concern. OWASP API Security Project.
