Skip to main content

SaaS API BOLA prevention: object-level authorization checklist

Prevent broken object-level authorization in SaaS APIs by checking each record and action against the signed-in user, tenant policy and relationship on every request.

In this guide

What is broken object-level authorization (BOLA)?

Broken object-level authorization (BOLA) occurs when an API accepts an object identifier but fails to check that the signed-in user may perform the requested action on that specific record. A user who can call an endpoint may still be unauthorized to read, change or delete another tenant’s object. Check authorization on the server for every object access; random IDs, hidden interface controls and authentication alone are not access control.

Authorize the user, object and requested action together

For every request that reads or changes a record, evaluate the current identity, the object’s tenant or owner relationship, the requested operation and the product’s sharing rules. A check that only compares a user ID with an object ID is insufficient when teams, delegated roles or shared resources are involved. Use the same policy for API, web and background-job paths.

Scope database access to the authorized tenant or relationship

Derive tenant context from a trusted authenticated identity and query only records the person may access. Avoid loading a global object by client-supplied ID and assuming the interface already filtered it. Apply the policy to nested resources, bulk operations, GraphQL resolvers, exports, search results and asynchronous jobs.

Keep object access separate from property-level permissions

A person may be allowed to view a record but not change its owner, billing status, role or security settings. Validate which fields can be read or updated for each operation and reject unexpected fields. Object-level authorization and property-level authorization address different decisions and both may be necessary.

API object authorization matrix
Role / tenant relationshipObject typeRead / update / deleteServer-side policyCross-tenant test
MemberReport
Workspace ownerMember record
Support operatorCustomer export

How do SaaS teams enforce object-level authorization consistently?

Centralize policy decisions without trusting caller-supplied ownership

Use a clear authorization policy or domain service so controllers, resolvers and jobs apply consistent rules. Treat IDs, tenant names and ownership fields from the request body as untrusted; the server should derive or verify relationships from authoritative records. A policy should fail closed when identity or tenant context is missing.

Apply authorization to every method and collection path

Review GET, POST, PATCH, PUT, DELETE, bulk actions, list filters, nested routes and alternate API versions. A secure detail endpoint does not help if an export, search or batch job returns the same objects without its check. Ensure that denied requests do not partially update a record or reveal sensitive fields in an error.

Use unpredictable identifiers only as defense in depth

UUIDs or opaque IDs can make casual enumeration harder, but they do not establish permission. An ID can be copied from a notification, browser history, log, shared link or another API response. Keep the object-level authorization check even when identifiers are difficult to guess.

How do you test BOLA across SaaS tenants and roles?

Build a cross-tenant and role-based test matrix

Create at least two test tenants with separate users and records, plus roles such as member, owner and support staff where they exist. For each object type, exercise allowed and denied read, update, delete and bulk actions. Test shared records and delegated access separately from ordinary tenant ownership.

Test the API boundary with another user’s object identifier

In a controlled environment, authenticate as one test user and request an object owned by another test user. Confirm the server denies the operation without disclosing sensitive fields, even if the client changes a path, query, header or body identifier. Repeat for each endpoint and nested relationship that uses a client-provided ID.

Add regression tests and audit denied access patterns

Keep automated tests that prove a user cannot access another tenant’s records across APIs, jobs and exports. Log the principal, object type, operation, tenant context and decision safely; avoid logging sensitive record contents. Alert on repeated denied cross-tenant attempts and review policy changes before release.

SaaS BOLA prevention questions

Is a tenant-ID comparison always sufficient?

Not by itself. Some records are shared, delegated or governed by role relationships, and a tenant value from the request may be forged. Derive context from trusted identity and evaluate the product’s actual access policy.

Does a secure web interface guarantee the API is safe?

No. Attackers and integrations can call APIs directly, and background jobs or exports may use different code paths. Enforce authorization on the server for every route, resolver, job and bulk operation.