Practical OWASP API Security Testing: Finding Broken Object Level Authorization (BOLA)
A practical approach to identifying object-level authorization weaknesses in modern APIs

Practical OWASP API Security Testing: Finding Broken Object Level Authorization (BOLA)
A practical approach to identifying object-level authorization weaknesses in modern APIs
Introduction
Modern applications increasingly rely on APIs to exchange data between web applications, mobile applications, and backend services. As APIs expose functionality and data directly to clients, weaknesses in authorization can have significant security consequences.
One of the most important API security issues to test for is Broken Object Level Authorization (BOLA).
BOLA occurs when an application fails to properly verify whether an authenticated user is authorized to access a specific object or resource. An attacker may be authenticated and have a valid session, but still be able to access another user’s data simply by modifying an object identifier in an API request.
For example, consider an endpoint such as:
GET /api/v1/orders/1001 HTTP/1.1
Authorization: Bearer <ACCESS_TOKEN>
If the authenticated user owns order 1001, the request may be legitimate.
However, if changing the identifier to:
GET /api/v1/orders/1002 HTTP/1.1
Authorization: Bearer <ACCESS_TOKEN>
returns another user’s order, the application may have a BOLA vulnerability.
The key issue is not whether the user is authenticated.
The key question is:
Is the authenticated user authorized to access the requested object?
This article presents a practical approach to testing for BOLA in APIs.
What is BOLA?
Broken Object Level Authorization (BOLA) occurs when an API does not properly enforce authorization checks on the objects or resources requested by an authenticated user.
In a typical application, users interact with resources that belong to them. These resources could include:
- User profiles
- Orders
- Invoices
- Transactions
- Documents
- Messages
- Account information
An API often identifies these resources using an object identifier.
For example:
GET /api/v1/orders/1001 HTTP/1.1
Authorization: Bearer <ACCESS_TOKEN>
In this example, 1001 represents the specific order being requested.
The API should not only verify that the access token is valid. It should also determine whether the authenticated user is authorized to access order 1001.
A BOLA vulnerability can occur when the API performs the first check but fails to perform the second.
For example, an application may correctly authenticate User A and then process the following request:
GET /api/v1/orders/1002 HTTP/1.1
Authorization: Bearer <USER_A_TOKEN>
If order 1002 belongs to User B but the API still returns the order information to User A, the application has failed to enforce object-level authorization.
The vulnerability can therefore be understood as a broken relationship between the authenticated user and the requested object:
Authenticated User
+
Requested Object
↓
Authorization Check
↓
Is the user allowed to access this object?
A secure API should perform this authorization check on the server side before returning or modifying the requested resource.
This is why BOLA testing is not simply about changing IDs in API requests. The objective is to determine whether the application’s authorization logic correctly enforces the relationship between users and the resources they are permitted to access.
Authentication vs Authorization
Understanding the difference between authentication and authorization is essential when testing for BOLA.
Authentication
Authentication answers:
Who are you?
For example, a user provides credentials and successfully logs into an application. The application may then issue an access token that is used to authenticate subsequent API requests.
A simplified flow might look like:
User
↓
Login
↓
Authentication
↓
Access Token
↓
API Request
A valid token tells the application that the request is associated with an authenticated identity.
Authorization
Authorization answers a different question:
What is this user allowed to access or do?
For example, User A may be authenticated successfully but should only be able to access resources belonging to User A.
A secure request should therefore involve both checks:
API Request
↓
Is the user authenticated?
↓
YES
↓
Is the user authorized for this object?
↓
YES NO
↓ ↓
Allow Reject
This distinction is particularly important with APIs because an application can have strong authentication while still having weak authorization.
A valid JWT, session, or API key does not automatically give a user permission to access every resource exposed by an API.
Understanding Object-Level Resources
To test effectively for BOLA, it is useful to understand what an object means in the context of an API.
An object is generally a specific resource that the application stores or manages.
Examples include:
user_id
account_id
order_id
invoice_id
transaction_id
document_id
profile_id
project_id
Consider:
GET /api/v1/orders/84521 HTTP/1.1
Authorization: Bearer <ACCESS_TOKEN>
Here, 84521 identifies a specific order.
Another example could be:
GET /api/v1/accounts/1001/transactions/5001 HTTP/1.1
Authorization: Bearer <ACCESS_TOKEN>
In this case, the request contains multiple identifiers.
The important question during testing is:
What relationship exists between the authenticated user and these objects?
For example:
User A
↓
Account 1001
↓
Transaction 5001
If User A is not authorized to access Account 1001 or Transaction 5001, the API should reject the request.
This relationship between the user and the resource is what makes object-level authorization so important.
How I Approach BOLA Testing
A practical BOLA assessment starts by understanding how the application handles authentication, users, and resources.
Rather than immediately changing identifiers, I first try to understand the application’s normal behavior.
A simplified testing process looks like this:
Understand the application
↓
Identify API endpoints
↓
Understand authentication
↓
Identify object identifiers
↓
Create authorized test accounts
↓
Capture legitimate requests
↓
Modify object references
↓
Replay requests
↓
Compare responses
↓
Verify authorization
↓
Assess impact
↓
Document findings
The purpose of this process is to determine whether the server consistently enforces authorization between the authenticated user and the requested object.
Identifying Potentially Vulnerable Endpoints
The first practical step is identifying API endpoints that interact with user-specific resources.
Tools such as browser developer tools, Burp Suite, or Postman can help reveal API requests during an authorized assessment.
Look for endpoints containing identifiers such as:
GET /api/v1/users/1001/profile
GET /api/v1/orders/84521
GET /api/v1/invoices/5002
GET /api/v1/documents/7811
The presence of an identifier does not automatically mean that the endpoint is vulnerable.
It simply makes the endpoint worth investigating.
Object references can also appear in query parameters:
GET /api/v1/orders?user_id=1001
or inside request bodies:
{
"user_id": 1001,
"order_id": 84521
}
They can also appear in nested resources:
GET /api/v1/accounts/1001/transactions/5001
Therefore, BOLA testing should not focus only on IDs appearing directly in URL paths.
Capturing a Legitimate Request
Once a potentially relevant endpoint has been identified, the next step is to capture a request that is legitimately authorized.
For example:
GET /api/v1/orders/84521 HTTP/1.1
Host: api.example.test
Authorization: Bearer <USER_A_TOKEN>
The server might respond with:
HTTP/1.1 200 OK
Content-Type: application/json
followed by the order information.
At this point, we know that User A can legitimately access order 84521.
The next question is whether the server properly distinguishes this resource from resources belonging to another user.
Manipulating the Object Identifier
The next step is to modify the object identifier while keeping the authenticated user’s context unchanged.
For example, the original request might be:
GET /api/v1/orders/84521 HTTP/1.1
Authorization: Bearer <USER_A_TOKEN>
The identifier can then be changed to another authorized test user’s resource:
GET /api/v1/orders/84522 HTTP/1.1
Authorization: Bearer <USER_A_TOKEN>
The important part is that the authentication token remains associated with User A.
The test is asking whether User A can access an object that belongs to User B.
A properly protected API should perform an authorization check before returning the resource.
For example:
User A
↓
Valid Access Token
↓
Request for Order 84522
↓
Server checks ownership
↓
Order belongs to User B
↓
Request rejected
A response such as:
HTTP/1.1 403 Forbidden
may indicate that the authorization boundary is being enforced.
Depending on the application’s design, the server may also return 404 Not Found rather than revealing whether the requested resource exists.
What a BOLA Vulnerability Looks Like
Consider the following scenario.
User A legitimately accesses:
GET /api/v1/orders/84521 HTTP/1.1
Authorization: Bearer <USER_A_TOKEN>
The server returns User A’s order.
The tester then changes the object identifier:
GET /api/v1/orders/84522 HTTP/1.1
Authorization: Bearer <USER_A_TOKEN>
Suppose order 84522 belongs to User B.
If the server responds:
HTTP/1.1 200 OK
and returns User B’s order information, this is a strong indication of an object-level authorization failure.
The important observation is:
Authenticated User: User A
Requested Resource: User B's Order
Authorization Result: Allowed
The server has successfully authenticated User A but has failed to enforce the authorization boundary around the requested object.
Testing More Than GET Requests
BOLA testing should not be limited to reading data.
Object-level authorization should also be evaluated on operations that modify or delete resources, where applicable.
Read
GET /api/v1/orders/84522
Can another user’s information be retrieved?
Update
PUT /api/v1/orders/84522
Can another user’s resource be modified?
Partial Update
PATCH /api/v1/orders/84522
Can information belonging to another user be changed?
Delete
DELETE /api/v1/orders/84522
Can another user’s resource be deleted?
Download
GET /api/v1/documents/84522/download
Can another user’s document be downloaded?
This is important because authorization must protect the action and the object, not just the endpoint.
An application may correctly restrict access to a resource when it is being viewed but fail to enforce the same authorization when the resource is updated or deleted.
Testing Different Object Locations
Object identifiers can appear in different parts of an API request.
URL path
GET /api/v1/orders/84521
Query parameter
GET /api/v1/orders?order_id=84521
Request body
{
"order_id": 84521
}
Nested resource
GET /api/v1/accounts/1001/orders/84521
Each of these cases should be considered during testing.
The location of the identifier does not determine whether authorization is required.
The application should enforce authorization wherever a user can interact with a protected resource.
Testing Horizontal and Vertical Access Controls
BOLA is particularly associated with horizontal authorization failures.
Horizontal access control concerns users with similar privileges accessing resources belonging to one another.
For example:
User A → User A's Order
User A → User B's Order
If User A can access User B’s order, there may be a horizontal authorization issue.
There is also another important access-control concept: vertical authorization.
This concerns users with different privilege levels.
For example:
Regular User
↓
Administrator Function
If a normal user can access functionality intended only for an administrator, that represents a different type of authorization failure.
Understanding both horizontal and vertical authorization helps provide a more complete picture of an application’s access-control model.
Why Changing an ID Is Not the Root Cause
It is common to describe BOLA simply as:
“Changing an ID allows access to another user’s data.”
While this describes a common testing technique, it does not describe the underlying security problem.
The actual issue is missing or improperly implemented server-side authorization.
An application should not rely on the frontend to determine which resources a user can access.
For example, the frontend may hide another user’s order from the user interface, but an attacker can interact directly with the API.
Similarly, changing sequential IDs to unpredictable identifiers does not eliminate the need for authorization.
For example:
1001
1002
1003
could be replaced with:
7c3b9e2a-...
f82a11d4-...
but if the server does not verify whether the authenticated user is authorized to access the resource, the underlying problem remains.
Unpredictable identifiers can reduce enumeration risk, but they are not a substitute for authorization.
Common BOLA Testing Mistakes
1. Testing with only one user
BOLA involves relationships between users and resources.
Testing with only one account makes it difficult to establish whether resources belonging to different users are properly isolated.
Using multiple authorized test accounts provides a clearer way to validate authorization boundaries.
2. Changing the ID and stopping at the response
A different response does not automatically mean that BOLA exists.
The tester should understand:
- Who owns the resource
- What the expected authorization behavior is
- What information was returned
- Whether the resource actually belongs to another user
3. Focusing only on sequential IDs
Object identifiers are not always numbers.
They may be:
- UUIDs
- Hashes
- Strings
- Emails
- Account references
- Composite identifiers
The testing principle remains the same: determine whether the authenticated user is authorized to access the referenced object.
4. Testing only GET requests
Authorization failures can affect reading, modifying, deleting, downloading, or performing actions against resources.
5. Assuming authentication equals authorization
A valid token proves that the requester has been authenticated.
It does not automatically prove that the requester is authorized to perform every action on every resource.
Remediation
The primary defense against BOLA is server-side authorization enforcement.
For every request involving a protected resource, the application should determine whether the authenticated user is authorized to perform the requested action on that specific object.
Conceptually:
const resource = await getOrder(orderId);
if (resource.ownerId !== authenticatedUser.id) {
return res.status(403).json({
error: "Forbidden"
});
}
The implementation will vary depending on the application’s architecture and authorization model.
In more complex applications, authorization may depend on multiple relationships:
User
↓
Role
↓
Organization
↓
Resource
↓
Action
For example, a user might be allowed to access resources belonging to their organization but not resources belonging to another organization.
The authorization logic should therefore reflect the application’s actual business rules.
Authorization checks should also be applied consistently across all relevant API operations.
Defense in Depth
Object-level authorization should be part of a broader API security strategy.
Other controls can complement authorization, including:
- Strong authentication
- Role-based or attribute-based access control
- Input validation
- Secure session management
- Rate limiting
- Logging and monitoring
- Consistent access-control policies
- Automated authorization testing
However, these controls should not be considered replacements for object-level authorization.
For example, rate limiting may slow down an attacker attempting to enumerate resources, but it does not fix the authorization failure itself.
The underlying authorization decision still needs to be correct.
A Practical BOLA Testing Checklist
When assessing an API in an authorized testing environment, the following checklist provides a useful starting point:
- Identify API endpoints that interact with protected resources.
- Understand how authentication is implemented.
- Create or obtain multiple authorized test accounts.
- Identify object-level identifiers.
- Capture legitimate requests for each test account.
- Replace object identifiers with identifiers belonging to another test account.
- Replay the request using the original authentication context.
- Compare the responses.
- Test identifiers in URL paths.
- Test identifiers in query parameters.
- Test identifiers in request bodies.
- Test nested resources.
- Test relevant GET operations.
- Test relevant POST, PUT, PATCH, and DELETE operations.
- Determine whether the server enforces ownership or access rights.
- Assess the information or functionality exposed.
- Document the affected resource, impact, and recommended remediation.
Key Takeaways
BOLA is fundamentally an authorization problem, not an authentication problem.
A user having a valid access token does not mean that the user should be able to access every resource exposed by an API.
When testing for BOLA, the most important relationship to understand is:
Authenticated User
+
Requested Object
+
Requested Action
↓
Authorization Decision
A secure API should verify this relationship on the server side for every protected operation.
Changing an object identifier is only the testing technique. The real question is whether the application’s authorization model correctly prevents users from accessing or manipulating resources they are not permitted to use.
API security testing therefore requires more than identifying endpoints and sending requests. It requires understanding how users, resources, permissions, and business rules interact.
Conclusion
BOLA remains an important area of API security testing because APIs often expose direct access to application resources.
A successful authentication process is only one part of the security boundary. Applications must also enforce authorization at the object level to ensure that users can access only the resources and actions they are permitted to use.
From a testing perspective, a structured approach is useful:
Identify the resource
↓
Understand the user context
↓
Capture a legitimate request
↓
Manipulate the object reference
↓
Verify authorization
↓
Assess the impact
↓
Document the finding
The goal is not simply to find whether an identifier can be changed.
The goal is to determine whether the API correctly enforces the application’s authorization rules.
That distinction is what turns a simple API request manipulation into meaningful security testing.
References
- OWASP API Security Top 10 — Broken Object Level Authorization (API1).
- OWASP Web Security Testing Guide — Authorization Testing.
- OWASP Application Security Verification Standard (ASVS) — Access Control Verification Requirements.
- OWASP API Security Project — API security guidance and testing resources.
About the Author
Chimezirim Oti is a cybersecurity practitioner focused on API security, application security, vulnerability management, and secure software development practices.
His interests include practical security assessment, vulnerability identification, API security testing, and helping organizations improve the security of their applications and infrastructure.
메타데이터
- post_id
- 95c87c3cc48b
- slug
- practical-owasp-api-security-testing-finding-broken-object-level-authorization-bola-95c87c3cc48b
- url
- https://medium.com/@otichimee/practical-owasp-api-security-testing-finding-broken-object-level-authorization-bola-95c87c3cc48b
- canonical_url
- https://medium.com/@otichimee/practical-owasp-api-security-testing-finding-broken-object-level-authorization-bola-95c87c3cc48b
- author_url
- https://medium.com/@otichimee
- status
- ok
- fetched_at
- 2026-08-22 22:25:02