Card 02/ 10
Object-Level Authorisation: Checking Every ID
Being logged in is not permission to read every order; the API must check each object belongs to the caller.
Broken object level authorisation, or BOLA, happens when an API checks that a caller is authenticated but not that the object they asked for is one they may access. Any id the client sends, in a path, a query or a body, can be changed to another user's. The fix is a check on every request that the object belongs to the caller, or that the caller has permission for it.
When The caller is not authenticated
, choose401 Unauthorized
When The order exists, and belongs to the caller or the caller has a role allowed to read any order
, choose200 with the order
When The order belongs to someone else, or does not exist
, choose404 Not Found, the same for both, so ids cannot be probed
What goes wrong. The handler loads the order by id and returns it. The token was valid, so the code looks secure, but nothing compared the order's owner with the caller.
A request that shows it. A customer who owns order 1001 sends GET /orders/1002 and receives a stranger's order. The same works for PUT, DELETE and any id in a body, such as "addressId": 77.
The fix. Scope every lookup to the caller, for example loading by id and customerId together, so another user's order is never found. Do it in one place, a repository method or a policy every handler uses, rather than remembering it per endpoint. Answer 404 rather than 403, so the response does not confirm the id exists.
How to test. Create two accounts, create an object with the first, and request it, change it and delete it with the second. Automate it for every endpoint that takes an id.
So never let an id from the client reach the database without the caller's identity beside it.
← → move through sections and cards