What is BOLA?
Imagine a coat check at a restaurant. You hand in your coat and get ticket #47. The rule is: whoever presents ticket #47 gets coat #47. Now imagine the coat check attendant hands over any coat to anyone who simply says a number — without checking that the ticket matches. That's BOLA.
BOLA (Broken Object Level Authorization) — formerly known as IDOR (Insecure Direct Object Reference) — is consistently ranked the number one vulnerability in APIs. It occurs when an API endpoint accepts an identifier (like a numeric ID in the URL or request body) but fails to verify that the currently authenticated user has permission to access that specific object.
The Attack Scenario
- Legitimate Request: You log in as User A (ID: 1001). You view your own profile.
GET /api/users/1001/profile Authorization: Bearer <your_token> - The Experiment: You wonder, "What happens if I change the number?"
GET /api/users/1002/profile Authorization: Bearer <your_token> - The Breach: If the server returns User 1002's profile, that is BOLA. Your token authenticated you as User 1001, but the server never checked whether User 1001 is authorized to read User 1002's data.
Why It Happens
Developers often implement Authentication ("Is this person logged in?") correctly but forget Authorization ("Does this person own or have permission to access this specific record?"). These are two separate checks, and APIs need both on every request that touches user-owned data.
The fix is always the same: after authenticating the request, look up the resource, then compare its owner to the authenticated user's identity before returning anything.
// VULNERABLE
app.get('/api/orders/:orderId', async (req, res) => {
const order = await Order.findById(req.params.orderId);
res.json(order); // No ownership check!
});
// SECURE
app.get('/api/orders/:orderId', async (req, res) => {
const order = await Order.findById(req.params.orderId);
if (!order || order.userId !== req.user.id) {
return res.status(403).json({ error: 'Forbidden' });
}
res.json(order);
});
Note that the secure version returns 403 Forbidden — not 404 Not Found — only if you want to confirm the resource exists. In high-security contexts, returning 404 for unauthorized resources is preferable because it prevents enumeration: an attacker can't distinguish "this record doesn't exist" from "this record exists but isn't yours."
Interviewers frequently ask: "What's the difference between authentication and authorization, and can you give a real API example?" A strong answer: "Authentication confirms who you are — typically via a JWT or session token. Authorization confirms what you're allowed to do. BOLA is a pure authorization failure: the API correctly identifies the user but never checks whether that user owns the requested resource. The fix is an ownership check on every object-level endpoint, not just a login gate."