---
title: "Preventing BOLA and Authorization Failures in APIs"
description: "Prevent broken object level authorization and cross-tenant API exposure with object checks, tenant-scoped data access, adversarial tests, logging, and incident response."
canonical_url: https://optimi.com/en/guides/preventing-bola-authorization-failures-apis
md_url: https://optimi.com/en/guides/preventing-bola-authorization-failures-apis.md
last_updated: 2026-07-15
---

# Preventing BOLA and Authorization Failures in APIs

An authenticated caller, valid token, and route-level permission do not prove that the caller may act on the specific object in the request.

Broken object level authorization, also called IDOR in many application contexts, occurs when a caller can alter an object reference and read, change, or delete a record without the required relationship. A WAF, rate limit, or API gateway can reduce abuse and validate coarse credentials; it is not normally the authority for the current relationship between caller A and object B.

## Outcome

Make object-level and tenant-scoped checks a release invariant across API routes, background work, storage, caches, and alternate service paths.

## Make the authorisation question explicit

Every object-bearing request needs a verified principal, requested action, specific object, tenant, and relevant context. Default deny, then grant through explicit ownership, membership, delegated relationship, role, or policy. Function-level permissions and object-level authorisation are complementary, not interchangeable.

**Object authorisation decision**

1. Verify principal — Validate issuer, audience, expiry, and credential context.
2. Derive tenant — Use trusted identity or workload context, never a client tenant header.
3. Load scoped object — Query within tenant and relationship scope.
4. Evaluate action — Apply ownership, policy, and contextual restrictions.
5. Record decision — Log safe evidence and return a consistent outcome.

*The service and data path must evaluate the relationship to the requested object after identity is verified and before data is returned or changed.*

**Object access requires identity, scope, and an action decision**

![Flowchart where an object-bearing API request first verifies a principal, derives trusted tenant and policy context, loads the object within tenant scope, and evaluates the requested action. Failed checks return an unauthenticated or consistent denial result; all outcomes record safe decision evidence.](/diagrams/preventing-bola-authorization-failures-apis/object-access-decision.svg)

*A valid token is only the starting point: the service must make a tenant-scoped decision about the requested object and action before returning or changing data.*

## Tenant-scope every access path

Scope database queries, list endpoints, bulk actions, caches, object-storage paths, queues, search indexes, GraphQL resolvers, and background consumers. UUIDs, signed IDs, and opaque URLs reduce easy enumeration but are never authorisation. A caller who obtains a valid identifier must still be denied without the relationship.

| Layer | Required control | Common bypass |
| --- | --- | --- |
| API handler | Object and action check | Route alias or alternate API version |
| Data access | Tenant-scoped query or row-level defence | Unscoped repository method |
| Cache | Tenant-aware eligibility and key | Cached decision survives membership change |
| Worker or export | Same policy context | Async job trusts submitted object ID |
| Gateway | Token and coarse route policy | Gateway assumed to know object relationship |

**Representative BOLA test result**

```
principal=tenant-A:user-1 action=read object=tenant-B:invoice-472
api_status=404 decision=deny policy_version=2026.07
cache_state=bypass audit_event=recorded
cross_tenant_regression=pass
```

## Test adversarially before release

Build an access-control matrix with at least two identities in one tenant and two tenants. For every object-bearing API, test read, create, update, delete, export, download, list, filter, pagination, batch, GraphQL, and asynchronous operations. Mutate object identifiers in paths, query parameters, body fields, nested objects, and signed URLs. A release should fail if a cross-user or cross-tenant operation succeeds.

Use `401` for absent or invalid authentication and `403` for an authenticated caller without permission. A consistent `404` can be an intentional design to hide object existence, but it must not mask an allow decision or make incident investigation impossible.

## Log decisions and prepare containment

Record timestamp, request ID, verified principal or workload identity, tenant, action, resource type, safe object reference, policy version, decision reason, and source service. Do not log tokens or full sensitive payloads. On suspected exposure, disable the vulnerable action, revoke affected sessions or keys, preserve evidence, identify affected tenants and objects, fix every alternate path, invalidate related caches and signed URLs, and add regression tests.

## BOLA prevention failures

- Trusting a `tenant_id` supplied by the caller or forwarding it without a protected proxy boundary.
  - Treating JWT scope as permission to every object of a type.
  - Applying checks in an HTTP handler but not exports, workers, GraphQL resolvers, or storage URLs.
  - Using WAF blocks or rate limits to mask a successful unauthorised request.

## Related guides

- [API Protection at the Edge](/en/guides/api-protection-edge)
- [Reliable API Design](/en/guides/reliable-api-design)
- [Secure Webhooks](/en/guides/secure-webhooks)

## Authoritative references

- [OWASP API1:2023 Broken Object Level Authorization](https://owasp.org/API-Security/editions/2023/en/0xa1-broken-object-level-authorization/)
- [OWASP Authorization Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Authorization_Cheat_Sheet.html)
- [OWASP Multi-Tenant Security Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Multi_Tenant_Security_Cheat_Sheet.html)
- [NIST SP 800-162: Attribute Based Access Control](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-162.pdf)
- [RFC 9700: OAuth 2.0 Security Best Current Practice](https://www.rfc-editor.org/rfc/rfc9700.html)

[Review API authorisation](/en/contact): Make tenant isolation an API invariant — Optimi can help connect route controls, origin authorisation, safe telemetry, and edge protection without pretending the edge owns object permissions.
