What Is BOLA and Why It Breaks SaaS APIs
A practical guide to Broken Object Level Authorization in multi-tenant SaaS APIs and the architecture patterns that prevent it.
What Is BOLA and Why It Breaks SaaS APIs
For adjacent controls, pair this with Secure API Authentication vs Authorization, Broken Access Control in SaaS Platforms, and Preventing Cross-Tenant Data Leakage in Multi-Tenant SaaS Systems.
For teams validating object-level authorization paths across tenants, Agnite Scan can be used as a reference implementation.
If you’re building a SaaS product, this is exactly the kind of issue that appears when tenant boundaries are not designed properly. Teams that need to design a SaaS system properly usually plan object access, tenant context, and release sequencing together.
When object IDs and tenant IDs travel through the same endpoint, a tenant isolation audit is the fastest way to verify the boundary under real request mutations.
Broken Object Level Authorization (BOLA) is one of the most dangerous vulnerability classes in modern SaaS APIs. It appears repeatedly in security incident reports, bug bounty programs, and real production breaches.
Unlike injection flaws or cryptographic failures, BOLA does not require complex exploitation. It occurs when an API exposes an object identifier and fails to verify that the requesting user is authorized to access that object.
In multi‑tenant SaaS systems this mistake can expose data belonging to other organizations. Because APIs power modern web applications, the impact can extend across entire datasets.
This article examines BOLA from an engineering architecture perspective. The goal is not only to describe the vulnerability but to explain why SaaS architectures make it easy to introduce and difficult to detect.
Problem Definition and System Boundary
A SaaS application typically exposes APIs that operate on resources.
Examples include:
- invoices\
- users\
- projects\
- documents\
- audit logs
Each resource is represented internally by an identifier. That identifier is passed through the API in URLs or request bodies.
Typical API patterns:
GET /api/projects/{projectId}GET /api/users/{userId}DELETE /api/invoices/{invoiceId}
These endpoints simply retrieve objects using an ID.
The security boundary appears when the system decides whether the requesting identity is allowed to access that object.
If the API only verifies authentication but does not verify ownership of the object, the endpoint becomes vulnerable to BOLA.
Example:
GET /api/projects/1824
becomes
GET /api/projects/1825
If the application does not verify tenant ownership, the API may return another organization’s data.
This failure occurs because object lookup and authorization are separated. Developers frequently retrieve the object first and assume it belongs to the requester.
That assumption breaks the security boundary.
Why SaaS Architectures Amplify BOLA
BOLA is especially dangerous in SaaS environments because most platforms operate on shared infrastructure.
Multiple tenants share:
- application servers\
- API endpoints\
- database clusters\
- object identifiers
Isolation is therefore enforced entirely through application logic.
Typical SaaS data model:
Project
Id
TenantId
Name
OwnerId
CreatedAt
Every API request accessing a project must verify tenant ownership.
If that verification fails even once, the API becomes a cross‑tenant data exposure vector.
Architectural Patterns That Prevent BOLA
Tenant‑Scoped Queries
Unsafe query:
var project = db.Projects
.FirstOrDefault(p => p.Id == projectId);Secure query:
var project = db.Projects
.FirstOrDefault(p =>
p.Id == projectId &&
p.TenantId == currentTenantId);Even if a user guesses another object’s ID, the database will not return the record.
Authorization becomes part of the query.
Centralized Authorization Policies
Example ASP.NET Core policy:
services.AddAuthorization(options =>
{
options.AddPolicy("ProjectAccess", policy =>
policy.RequireAssertion(context =>
{
var tenantId = context.User.FindFirst("tenant_id").Value;
var projectTenantId = context.Resource.TenantId;
return tenantId == projectTenantId;
}));
});Row Level Security
Example PostgreSQL policy:
CREATE POLICY tenant_isolation
ON projects
USING (tenant_id = current_setting('app.tenant_id')::uuid);The database automatically filters rows belonging to other tenants.
Implementation Example in ASP.NET Core
Unsafe endpoint:
[HttpGet("{projectId}")]
public async Task<IActionResult> GetProject(Guid projectId)
{
var project = await _db.Projects
.FirstOrDefaultAsync(p => p.Id == projectId);
if (project == null)
return NotFound();
return Ok(project);
}Secure endpoint:
[HttpGet("{projectId}")]
public async Task<IActionResult> GetProject(Guid projectId)
{
var tenantId = _tenantProvider.GetTenantId();
var project = await _db.Projects
.FirstOrDefaultAsync(p =>
p.Id == projectId &&
p.TenantId == tenantId);
if (project == null)
return NotFound();
return Ok(project);
}Real Failure Scenario
A SaaS analytics platform exposes:
GET /api/reports/{reportId}
Database schema:
Report
Id
TenantId
Name
DataBlob
CreatedAt
Implementation:
var report = db.Reports
.FirstOrDefault(r => r.Id == reportId);Developers assume GUIDs are unguessable.
Attackers obtain IDs through:
- shared URLs\
- browser tools\
- network logs
Once discovered, attackers request reports directly.
Because tenant ownership is not verified, the API returns data belonging to another organization.
This becomes a cross‑tenant breach.
Operational Considerations
Security Testing
Integration tests should simulate cross‑tenant access.
Logging Suspicious Access
Monitoring should detect repeated access attempts for unknown object IDs.
API Design Reviews
Every endpoint accepting identifiers should answer:
Who owns this object and where is ownership enforced.
Relationship to SaaS Security Architecture
BOLA is not just an API bug. It is a structural failure in how authorization integrates with system architecture.
Secure SaaS systems enforce authorization across:
- identity propagation\
- tenant context resolution\
- database queries\
- background workers\
- caching layers
Object retrieval must always include ownership verification.
Verify object-level authorization before release
We test whether object IDs, tenant context, and ownership checks still line up under real API requests. The goal is to catch BOLA and cross-tenant exposure before users do.
Need implementation support? Review the Agnite Scan case study or explore our services.
Related Articles
Continue reading in SaaS Security
Building SaaS with complex authorization?
Move from theory to request-level validation and architecture decisions that hold under scale.
SaaS Security Cluster
This article is part of our SaaS Security Architecture series.
Start with the pillar article: SaaS Security Architecture: A Practical Engineering Guide
