Object-Level Authorization
also called BOLA, IDOR
Checking that the caller is entitled to the specific record they requested, not merely that they may call the endpoint.
The most common serious API vulnerability, consistently at the top of the OWASP API risk list, and one of the easiest to introduce.
The pattern is always the same: the handler verifies the caller is authenticated and permitted to call
GET /orders/{id}, then fetches the order by ID and returns it — without checking that the order
belongs to that caller. Changing the ID in the URL returns someone else's data.
It is easy to introduce because the check is per record, so it must appear in every handler that retrieves, updates or deletes a record. One handler missing it is a breach, and there is nothing in the framework that notices.
The defences that scale better than diligence:
Scope the query rather than checking after fetching. WHERE id = ? AND customer_id = ? cannot
return the wrong record. This is far more robust than fetching and comparing, because forgetting it
returns nothing rather than returning someone else's data.
Enforce at the data-access layer, so authorisation is applied by construction — row-level security in the database, or a repository that requires a caller context.
Use unguessable identifiers. Not a defence on its own, and it removes trivial enumeration.
Test for it automatically: an authenticated request from user A for user B's resources, generated across every endpoint in the API specification.