Overview
APIs constantly refer to specific objects by an identifier in the URL or body — /api/v1/notes/42, /api/v1/users/1007. If the server returns or modifies the requested object without checking that the caller is allowed to access that particular object, an attacker can simply change the id to reach someone else's data. This flaw — known as BOLA (Broken Object Level Authorization) or, historically, IDOR (Insecure Direct Object Reference) — is the single most common and impactful API vulnerability. This lesson explains it and, importantly, how to defend against it.
Learning objectives
- Define object-level authorization and explain BOLA/IDOR.
- Describe why predictable object identifiers increase exposure.
- Explain why authentication alone does not prevent BOLA.
- Apply the correct defense: per-object authorization on every request.
Core concept
An object identifier selects a specific record — a note, an order, a user. Object-level authorization is the check that confirms this authenticated caller is permitted to act on this specific object. BOLA / IDOR is the vulnerability that occurs when that check is missing: the server trusts the id supplied by the client and returns or changes the object without confirming ownership or permission.
The key insight is that authentication is not authorization. A user may be perfectly, legitimately logged in (authenticated) and still not be allowed to read object 42. If the server only checks "are you logged in?" and not "is object 42 yours?", then any logged-in user can access every object by changing the id.
How it works
Consider a route that reads a note by id:
GET /api/v1/notes/42 -> returns note 42
A vulnerable server looks up note 42 and returns it as long as the request is authenticated. Because ids are often sequential and predictable, an attacker who owns note 41 can request 42, 43, 44... and enumerate other users' notes. The identifier being guessable makes enumeration trivial, but note that the root cause is the missing authorization check, not the format of the id.
The correct behavior is: on every request, the server must verify that the authenticated user has permission for the specific object before returning or modifying it — for example, confirming the note's owner matches the caller, or that the caller's role grants access. If not, it returns 403 Forbidden (or 404 to avoid confirming the object exists).
Practical example
In an isolated lab API, you authenticate as your own test user and read your own note at /api/v1/notes/1001. Testing responsibly and within scope, you change the id to /api/v1/notes/1002 — an object belonging to a different test account. The server returns it, revealing that it never checked ownership. You confirm the pattern on a couple of adjacent ids to demonstrate impact, document it, and stop; you do not harvest data. The remediation is clear: the handler must compare the object's owner to the authenticated caller and refuse the request when they differ. Switching to unpredictable identifiers (like random UUIDs) raises the bar for enumeration, but it is a defense-in-depth measure — the essential fix is the server-side authorization check.
Cybersecurity relevance
BOLA is ranked the number-one API security risk by the industry because it is common, easy to exploit, and directly exposes other users' data. It appears anywhere an API accepts a client-supplied identifier — path parameters, query strings, request bodies, and even ids buried inside tokens. Defenses, in order of importance: enforce object-level authorization on every request (never trust the client's id alone), derive the caller's identity from the verified session/token rather than from a client-supplied field, prefer non-guessable identifiers as a hardening layer, and add logging to detect enumeration patterns. Because the check must exist on every object-accessing endpoint, centralizing authorization logic reduces the chance of forgetting it on one route.
Common mistakes
- Checking only authentication, not object-level authorization — the defining cause of BOLA.
- Relying on unguessable ids as the sole protection instead of an actual permission check.
- Trusting a user id supplied by the client (in a body or parameter) instead of the verified identity from the token/session.
- Protecting the read endpoint but not the update/delete endpoints for the same object (ties back to per-method checks).
Key takeaways
- Object-level authorization confirms the authenticated caller may act on the specific object requested; BOLA/IDOR is the flaw of omitting that check.
- Authentication is not authorization — a logged-in user must still be checked against each object they request.
- Predictable, sequential ids make enumeration easy, but the root cause and the real fix is the server-side per-object authorization check.
- BOLA is the top API risk; defend with per-request authorization, identity taken from the verified token, non-guessable ids as hardening, and enumeration monitoring.
Check your understanding
- Why does using random, unguessable object identifiers fail to fully fix a BOLA vulnerability on its own?
- Where should the server get the caller's identity when deciding object-level access, and why not from a client-supplied field?

