

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 authorisation 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 authorisation. If you can obtain another valid identifier through a list endpoint, notification, browser history, mobile response or predictable workflow, the authorisation 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 authorisation.
Interactive: expected vs. vulnerable behaviour
Keyboard: ← → · Respects reduced-motion (no autoplay).
Change the requested object
Authorisation 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 authorised | Deny | Deny |
What strong authorisation looks like
Enforce authorisation 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 authorisation 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 authorisation as a central API security concern. OWASP API Security Project.
Related research: API authorisation attack chains · API security testing.
Frequently asked questions
What is BOLA?
Broken Object Level Authorization: the API fails to verify that the caller is allowed to act on the specific object identified in the request.
Does changing an ID prove BOLA?
Only if the server returns or modifies another principal’s object without an authorisation check. Guessing IDs alone is not the finding—the missing decision is.
Does BOLA apply to GraphQL?
Yes. Resolvers and nested fields need object-level checks just as REST path parameters do.
How do you reduce false positives?
Use two authenticated roles or tenants, confirm ownership expectations, and document the exact failed control.
