September 3, 2026
IDOR to BOLA โ Mastering Authorization Bugs in Bug Bounty
From Simple ID Manipulation to Advanced Authorization Testing

By mahfujwhh
7 min read
From Simple ID Manipulation to Advanced Authorization Testing
One of the first vulnerabilities many bug bounty hunters learn is IDOR.
It looks simple:
GET /api/users/1001GET /api/users/1001Change:
1001 โ 10021001 โ 1002And suddenly you see another user's information.
But that's only the beginning.
Modern authorization vulnerabilities are much broader than simply changing an ID.
They can involve:
- Users
- Organizations
- Teams
- Projects
- Invoices
- Orders
- Files
- API keys
- Roles
- Permissions
- Tenants
- Administrative functions
And this is where IDOR evolves into BOLA, BFLA, privilege escalation, cross-tenant access, and complex authorization flaws.
This article explains how to go from understanding basic IDOR to developing an advanced authorization-testing methodology.
Table of Contents
- What Is Authorization?
- Authentication vs Authorization
- What Is IDOR?
- A Simple IDOR Example
- Horizontal Privilege Escalation
- Vertical Privilege Escalation
- IDOR in APIs
- What Is BOLA?
- IDOR vs BOLA
- BFLA
- Nested Object Authorization
- Cross-Account Authorization
- Cross-Tenant Authorization
- Authorization in Different HTTP Methods
- Authorization Beyond IDs
- Advanced Authorization Testing
- How to Test Authorization Systematically
- Multiple-Account Testing
- Business Logic + Authorization
- Common False Positives
- Impact
- Authorization Testing Checklist
1. What Is Authorization?
Authorization is the process of deciding:
What is this authenticated user allowed to access or perform?
Imagine an application has:
User A
โ
Project A
User B
โ
Project BUser A
โ
Project A
User B
โ
Project BThe application must enforce:
User A โ Project A โ
User A โ Project B โUser A โ Project A โ
User A โ Project B โIf the server fails to enforce that boundary, we may have an authorization vulnerability.
APPLICATION
โ
โโโโโโโโโโดโโโโโโโโโ
โผ โผ
User A User B
โ โ
โผ โผ
Project A Project B
โ โ
โโโโโโโโXโโโโโโโโโโ
Authorization
Boundary APPLICATION
โ
โโโโโโโโโโดโโโโโโโโโ
โผ โผ
User A User B
โ โ
โผ โผ
Project A Project B
โ โ
โโโโโโโโXโโโโโโโโโโ
Authorization
BoundaryThe key point:
Authorization must be enforced by the server.
A frontend button being hidden is not authorization.
2. Authentication vs Authorization
These two concepts are frequently confused.
Authentication
Answers:
Who are you?
Example:
Username+Password= Authenticated UserUsername+Password= Authenticated UserAuthorization
Answers:
What are you allowed to do?
For example:
Authenticated User
โ
Regular User
โ
Can view own invoices
โ
Cannot view other users' invoices
โ
Cannot access admin functionsAuthenticated User
โ
Regular User
โ
Can view own invoices
โ
Cannot view other users' invoices
โ
Cannot access admin functions[Authentication vs Authorization]
AUTHENTICATION
โ
โผ
WHO ARE YOU?
โ
โผ
Logged In
โ
โผ
AUTHORIZATION
โ
โผ
WHAT CAN YOU DO?AUTHENTICATION
โ
โผ
WHO ARE YOU?
โ
โผ
Logged In
โ
โผ
AUTHORIZATION
โ
โผ
WHAT CAN YOU DO?A user being authenticated does not mean they are authorized to access everything.
3. What Is IDOR?
IDOR stands for:
Insecure Direct Object Reference
The basic idea is simple. An application exposes a direct reference to an object:
GET /api/invoices/1001GET /api/invoices/1001The server should verify:
Does invoice 1001 belong to this user?Does invoice 1001 belong to this user?If it simply retrieves the object:
invoice = database.find(1001)invoice = database.find(1001)without checking ownership, the application may be vulnerable.
4. A Simple IDOR Example
Imagine two accounts:
Account A
User ID: 101
Account B
User ID: 202Account A
User ID: 101
Account B
User ID: 202Account A creates:
Invoice ID: 5001Invoice ID: 5001Account B creates:
Invoice ID: 5002Invoice ID: 5002Account A sends:
GET /api/invoices/5001
Authorization: Bearer USER_A_TOKENGET /api/invoices/5001
Authorization: Bearer USER_A_TOKENResponse:
{
"id": 5001,
"owner": 101,
"amount": 500
}{
"id": 5001,
"owner": 101,
"amount": 500
}Now, in an authorized test environment, the researcher checks:
GET /api/invoices/5002
Authorization: Bearer USER_A_TOKENGET /api/invoices/5002
Authorization: Bearer USER_A_TOKENIf the server returns Account B's invoice, the important observation is:
Authenticated as A
โ
Requested B's object
โ
Server returned B's object
โ
Ownership check failedAuthenticated as A
โ
Requested B's object
โ
Server returned B's object
โ
Ownership check failedThat is the essence of object-level authorization failure.
[ IDOR flow]
USER A TOKEN
โ
โผ
/api/invoices/5002
โ
โผ
Server
โ
โโโ Is invoice 5002 owned by A?
โ
โโโ โ No ownership check
โ
โผ
Invoice B returnedUSER A TOKEN
โ
โผ
/api/invoices/5002
โ
โผ
Server
โ
โโโ Is invoice 5002 owned by A?
โ
โโโ โ No ownership check
โ
โผ
Invoice B returned5. Horizontal Privilege Escalation
Horizontal access means:
One user accesses another user's resources at the same privilege level.
Example:
User A
โ
Own profile โ
User A
โ
User B profile โUser A
โ
Own profile โ
User A
โ
User B profile โBoth users are regular users and same role.
Therefore:
Same privilege+Different object = Horizontal authorization issueSame privilege+Different object = Horizontal authorization issueCommon targets include:
- Profiles
- Orders
- Invoices
- Documents
- Messages
- Tickets
- Projects
- API keys
- Payment records
6. Vertical Privilege Escalation
Vertical privilege escalation is different.
Here the attacker moves from a lower privilege level to a higher privilege level.
For example:
Regular User
โ
Admin Function or higher userRegular User
โ
Admin Function or higher userImagine:
POST /api/admin/users/123/disablePOST /api/admin/users/123/disableA normal user should receive:
403 Forbidden403 ForbiddenIf the server performs the administrative action instead, the issue is much more serious.
[ Horizontal vs Vertical]
PRIVILEGE
โฒ
โ
Admin โ
โ
โ โ Vertical
โ
User โ
โ
โโโโโโโโโโโโโโโโบ Objects
HorizontalPRIVILEGE
โฒ
โ
Admin โ
โ
โ โ Vertical
โ
User โ
โ
โโโโโโโโโโโโโโโโบ Objects
Horizontal7. IDOR in APIs
Modern IDOR vulnerabilities frequently appear inside APIs.
For example:
GET /api/v1/users/123GET /api/v1/users/123or:
GET /api/v1/orders/9876GET /api/v1/orders/9876or:
GET /api/v1/projects/456GET /api/v1/projects/456or:
GET /api/v1/documents/321GET /api/v1/documents/321The identifier may be:
Integer
UUID
Encoded value
Slug
Filename
Reference number
Database keyInteger
UUID
Encoded value
Slug
Filename
Reference number
Database keyDon't assume:
"It's a UUID, so it isn't vulnerable."
Predictability is not the requirement. and can find uuid using recon (web archive, virustotal, usrlsacn etc)
Authorization failure is the requirement.
8. What Is BOLA?
BOLA stands for:
Broken Object Level Authorization
It is an API security problem where the API fails to properly verify whether the authenticated user is authorized to access or manipulate a specific object.
For example:
User A
โ
GET /api/orders/order-AUser A
โ
GET /api/orders/order-Aworks correctly.
But:
User A
โ
GET /api/orders/order-BUser A
โ
GET /api/orders/order-Balso works even though Order B belongs to User B.
That's a BOLA scenario.
9. IDOR vs BOLA
These concepts overlap, but they aren't exactly the same terminology.
IDOR
Traditionally describes insecure direct references to objects.
BOLA
Is the API-security terminology emphasizing failure to enforce authorization at the object level.
Think of it like:
IDOR
โ
โโโ Web applications
โโโ APIs
BOLA
โ
โโโ API object authorizationIDOR
โ
โโโ Web applications
โโโ APIs
BOLA
โ
โโโ API object authorizationA useful mindset is:
Don't focus on the acronym. Focus on the authorization decision.
10. BFLA
BFLA means:
Broken Function Level Authorization
BOLA asks:
Can I access someone else's object?
BFLA asks:
Can I execute a function I shouldn't be allowed to execute?
For example:
POST /api/admin/users/123/deletePOST /api/admin/users/123/deleteA regular user should not be able to perform this function.
The server should enforce:
User
โ
Role = user
โ
Admin function?
โ
NO
โ
403User
โ
Role = user
โ
Admin function?
โ
NO
โ
403If the function executes anyway, that's a function-level authorization problem.
11. Nested Object Authorization
This is where authorization testing becomes more interesting.
Consider:
Organization
โโโ Project
โโโ Invoice
โโโ PaymentOrganization
โโโ Project
โโโ Invoice
โโโ PaymentAn application may correctly protect the top-level object but fail to protect a nested object.
For example:
GET /api/organizations/A/projects/123/invoices/456GET /api/organizations/A/projects/123/invoices/456A researcher should think:
Does the user have access to:
Organization A?
Project 123?
Invoice 456?Does the user have access to:
Organization A?
Project 123?
Invoice 456?Authorization should be checked across the entire object hierarchy.
[ Nested authorization]
Organization
โ
โผ
Project
โ
โผ
Invoice
โ
โผ
Payment
Every layer needs authorization.Organization
โ
โผ
Project
โ
โผ
Invoice
โ
โผ
Payment
Every layer needs authorization.12. Cross-Account Authorization
Many applications allow users to interact with other users.
Examples:
Invite
Share
Transfer
Collaborate
Assign
Mention
Send
Export
DownloadInvite
Share
Transfer
Collaborate
Assign
Mention
Send
Export
DownloadThese workflows create interesting authorization boundaries.
Example:
Account A
โ
Creates Project
โ
Invites Account BAccount A
โ
Creates Project
โ
Invites Account BNow ask:
What happens if Account B attempts to access objects that belong only to Account A?
Or:
What happens after Account B is removed?
Authorization must remain correct throughout the object's lifecycle.
13. Cross-Tenant Authorization
This is especially important in SaaS applications.
Imagine:
Tenant A
โโโ User A1
โโโ User A2
โโโ Projects
Tenant B
โโโ User B1
โโโ User B2
โโโ ProjectsTenant A
โโโ User A1
โโโ User A2
โโโ Projects
Tenant B
โโโ User B1
โโโ User B2
โโโ ProjectsThe application must enforce:
Tenant A โ Tenant BTenant A โ Tenant BA cross-tenant authorization issue can be significantly more serious because one customer may access another customer's data.
[ Multi-tenant isolation]
SaaS APPLICATION
โ
โโโโโโโโโโโดโโโโโโโโโโ
โผ โผ
TENANT A TENANT B
โ โ
Users Users
Projects Projects
Invoices Invoices
โ โ
โโโโโโโโโXโโโโโโโโโโโ
IsolationSaaS APPLICATION
โ
โโโโโโโโโโโดโโโโโโโโโโ
โผ โผ
TENANT A TENANT B
โ โ
Users Users
Projects Projects
Invoices Invoices
โ โ
โโโโโโโโโXโโโโโโโโโโโ
Isolation14. Authorization Across HTTP Methods
Don't test only GET.
An object might be protected for reading but improperly protected for modification.
Test the application's intended methods in an authorized lab or program:
GET
POST
PUT
PATCH
DELETEGET
POST
PUT
PATCH
DELETEFor example:
GET /api/project/123
PATCH /api/project/123
DELETE /api/project/123GET /api/project/123
PATCH /api/project/123
DELETE /api/project/123Ask:
Can I read it?
Can I modify it?
Can I delete it?
Can I perform an action on it?Can I read it?
Can I modify it?
Can I delete it?
Can I perform an action on it?Different functions may have different authorization controls.
15. Authorization Beyond IDs
A common beginner mistake is thinking:
"IDOR means changing an ID."
That's too narrow.
Object references can appear in:
Path
Query parameter
JSON body
Form data
Headers
Cookies
GraphQL variables
Multipart fieldsPath
Query parameter
JSON body
Form data
Headers
Cookies
GraphQL variables
Multipart fieldsExample:
{
"project_id": "123"
}{
"project_id": "123"
}or:
?project_id=123?project_id=123or:
/api/projects/123/api/projects/123The important question is always:
Does the server verify that this object belongs to the current user's authorized scope?
16. Advanced Authorization Testing
Once basic testing becomes natural, start looking at relationships.
Think in terms of:
USER
โ
ROLE
โ
ORGANIZATION
โ
TEAM
โ
PROJECT
โ
RESOURCE
โ
ACTIONUSER
โ
ROLE
โ
ORGANIZATION
โ
TEAM
โ
PROJECT
โ
RESOURCE
โ
ACTIONFor each relationship ask:
Who owns it?
Who can read it?
Who can modify it?
Who can delete it?
Who can share it?
Who can transfer it?
Who can administer it?Who owns it?
Who can read it?
Who can modify it?
Who can delete it?
Who can share it?
Who can transfer it?
Who can administer it?This turns authorization testing into a structured methodology.
17. How to Test Authorization Systematically
Instead of randomly changing IDs, create a matrix.
Instead of randomly changing IDs, create a matrix.
Object User A User B Admin
Project A โ ? โ
Project B ? โ โ
Invoice A โ ? โ
Invoice B ? โ โ
Admin Settings โ โ โInstead of randomly changing IDs, create a matrix.
Object User A User B Admin
Project A โ ? โ
Project B ? โ โ
Invoice A โ ? โ
Invoice B ? โ โ
Admin Settings โ โ โThen verify the expected behavior.
This is much more powerful than random testing.
18. Multiple-Account Testing
Multiple test accounts are one of the most useful techniques for authorization research.
Create:
Account A
Account BAccount A
Account BWhere permitted.
Then:
A creates Object A
B creates Object BA creates Object A
B creates Object BCapture requests from A.
Then determine whether the same action against B's object is correctly denied.
The key is to preserve a clean separation:
A token โ A object
B token โ B objectA token โ A object
B token โ B objectThis gives you a reliable authorization baseline.
19. Business Logic + Authorization
Some of the most interesting bugs occur when authorization interacts with business logic.
Imagine:
User
โ
Free Plan
โ
Invite MemberUser
โ
Free Plan
โ
Invite MemberThe frontend might hide the invitation feature.
But the backend might still accept the API request.
The problem isn't merely:
"I found a hidden endpoint."
The real question is:
Does the backend enforce the subscription restriction?
Another example:
Order
โ
Payment
โ
Refund
โ
Account creditOrder
โ
Payment
โ
Refund
โ
Account creditAuthorization and business logic may interact in unexpected ways.
This is why advanced hunters study workflows rather than isolated endpoints.
20. Common False Positives
Not every successful request is a vulnerability.
Public objects
Some objects are intentionally public.
Shared resources
A resource may legitimately belong to multiple users.
Admin access
An administrator may legitimately access another user's data.
Predictable IDs
Predictable IDs alone are not a vulnerability.
Hidden endpoints
A hidden endpoint is not automatically vulnerable.
Different response codes
A different response does not necessarily prove unauthorized access.
Always establish:
Unauthorized access
+
Sensitive action/data
+
Security impactUnauthorized access
+
Sensitive action/data
+
Security impact21. Impact
Impact determines how serious the issue is.
Consider the difference between:
Can view another user's public usernameCan view another user's public usernameand:
Can access another user's private invoicesCan access another user's private invoicesand:
Can modify another user's accountCan modify another user's accountand:
Can perform administrative actionsCan perform administrative actionsThe vulnerability class alone doesn't determine severity.
You need to explain the actual security consequence.
22. Authorization Testing Checklist
Use this checklist during authorized testing:
[ ] Multiple accounts created
[ ] User-owned objects identified
[ ] Roles identified
[ ] Organization boundaries identified
[ ] Team boundaries identified
[ ] Object relationships mapped
[ ] GET authorization tested
[ ] Modification authorization tested
[ ] Delete authorization tested
[ ] Administrative functions checked
[ ] Nested resources checked
[ ] Cross-account boundaries checked
[ ] Cross-tenant boundaries checked
[ ] Subscription restrictions checked
[ ] Sharing/invitation workflows checked
[ ] Object lifecycle checked
[ ] Impact validated[ ] Multiple accounts created
[ ] User-owned objects identified
[ ] Roles identified
[ ] Organization boundaries identified
[ ] Team boundaries identified
[ ] Object relationships mapped
[ ] GET authorization tested
[ ] Modification authorization tested
[ ] Delete authorization tested
[ ] Administrative functions checked
[ ] Nested resources checked
[ ] Cross-account boundaries checked
[ ] Cross-tenant boundaries checked
[ ] Subscription restrictions checked
[ ] Sharing/invitation workflows checked
[ ] Object lifecycle checked
[ ] Impact validated