No. Comparing the user ID in the token with an ID in the URL covers only the simplest cases, such as a profile route that takes the user's own ID. Most objects, like invoices, shops or documents, have their own IDs, so you must check that this user may perform this action on this specific object.
What OWASP says
The OWASP API Security Top 10 entry for broken object level authorization states that comparing the user ID of the current session, for example extracted from the JWT, with the vulnerable ID parameter is not a sufficient solution. It could address only a small subset of cases.
The entry also explains why BOLA is so common in APIs. The server usually does not track the client's state and relies on parameters like object IDs sent by the client to decide which objects to access.
Why the comparison falls short
The check works when the object is the user. For everything else it breaks, because the ID in the path is not a user ID.
| Request | ID compared | Problem |
|---|---|---|
| GET /users/42 | Token sub equals 42 | Works for this route |
| GET /invoices/9001 | Nothing to compare | Who owns invoice 9001? |
| GET /shops/acme/revenue | Shop name | A user may own several shops, or none |
| POST /teams/7/members | Team 7 | Needs role in team 7, not user equality |
The OWASP entry gives a scenario of exactly this shape. An e-commerce platform exposes revenue data at a path with the shop name. An attacker lists all shop names through another endpoint and swaps each one into the URL. Nothing about the attacker's own user ID was ever in play.
What a real object check looks like
The entry says every endpoint that receives an object ID and acts on the object should implement object-level authorization checks, validating that the logged-in user has permission to perform the requested action on the requested object.
- Load the object by ID, scoped to what the caller may reach. In a multi-tenant system, include the tenant in the lookup.
- Evaluate ownership, membership or relationship between the caller and the object.
- Evaluate the action. Read and delete are different permissions.
- Deny and log if any step fails.
- Do this in a shared layer, not by hand in every handler.
OWASP's IDOR prevention sheet adds a practical technique: when looking up objects by primary key, use datasets the user has access to, such as the user's own records collection, instead of querying the whole table.
Do random IDs fix it?
The IDOR sheet says complex identifiers such as GUIDs make guessing impractical but that access control checks are still essential, since an attacker who obtains a URL should still be blocked. Treat random IDs as defense in depth.
BOLA or BFLA
If an attacker reaches an endpoint they should never access, that is broken function level authorization. If they use an allowed endpoint but swap the object ID, that is BOLA. The fix for the first is a role or scope check, and for the second an object check. Many APIs need both.
How to test
Use the two-account method the IDOR sheet describes: create user A and user B, each with their own objects, then as A try B's objects across read, create, update, delete, export and admin actions. Do it with predictable and unguessable IDs alike.
Try it yourself
Click through it at your own pace, or open it full screen. Look at how a scan varies parameters against a running app.
Safeguard supports dependency scanning, reachability analysis and policy gates, with a free scan at gold.safeguard.sh/scan.
Quick check
Is checking tenant ID enough?
It stops cross-tenant reads but not access to another user's object inside the same tenant. You usually need an object check as well.
Where should the check live?
In a shared authorization layer that every route passes through, so a new endpoint cannot skip it by accident.
Sources
- OWASP API1:2023 Broken Object Level Authorization
- OWASP Insecure Direct Object Reference Prevention Cheat Sheet
- OWASP API5:2023 Broken Function Level Authorization
Last reviewed: 19 October 2026.