An alternate-key lookup still needs object authorization
Most BOLA writeups show GET /orders/{id} with a guessed UUID. The same bug often hides behind a “friendlier” lookup: GET /orders?email= , findByExternalId , or where slug = ? . If the handler resolves a row by email, SKU, username, or external id and returns it whenever some row matches — without proving the authenticated subject may access that row — you still have broken object authorization.…
Many online resources illustrate a security flaw by using a GET request like GET /orders/{id} with an assumed UUID. This same vulnerability can also arise from more user-friendly approaches such as GET /orders?email=, findByExternalId, or slug = ?. If the system retrieves a row based on email, SKU, username, or external ID and returns it whenever any row matches, without ensuring the authenticated user has permission to access that row, then object authorization has been compromised.
The primary key's opacity is not the actual source of control. The oversight is in not checking if the user can perform the action on the specific resource after resolving it. Effective practices include resolving by an alternate key, then authorizing the loaded resource for the specific subject (tenant, ownership, relationship), and not assuming "we found a row" means "they may see it".
The same authorization rules should apply to both list and single-resource routes. If GET /orders is restricted to the caller's tenant, then GET /orders/by-email must also respect this same restriction and not utilize a global unique index. It is advisable to use the same denial shape as your id-based routes (often a 404 error) so alternate keys do not inadvertently function as an existence oracle across different tenants.
Logging the resolved resource ID on a denial should be a standard practice. A simple test is to attempt to access another user's order using their email or external ID while acting as that other user. If the system grants access, then the security gate failed not because a row doesn't exist, but because authorization was missing.
Remember, lookups are merely conveniences, but authorization is fundamentally about the object, not the shape of the key.
Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.