IDOR (Insecure Direct Object Reference): Definition, How It Works, and Where You’ll See It
IDOR (Insecure Direct Object Reference) is an authorization vulnerability where an application exposes a direct reference to an internal object (like a record ID, filename, or UUID) and fails to verify the requester is allowed to access that specific object.
IDOR (Insecure Direct Object Reference) is a broken access control and authorization vulnerability where a user can access (or modify/delete) another user’s resources simply by changing an identifier in a URL or API request—like switching /invoice/123 to /invoice/124. Because IDOR often leads directly to data exposure or account-impacting actions, it should be treated as a high-urgency finding in web application security and API security programs.
How IDOR works
IDOR happens when an application’s access control logic is incomplete or misplaced. The app might authenticate a user correctly (session, token, SSO), but then trusts the client-supplied object reference to decide what object to operate on—without a server-side check that the user is authorized for that object.
Typical flow
- A user requests a resource that belongs to them:
-
GET /api/invoices/1001 - The server looks up invoice
1001and returns it, but doesn’t check ownership/permission. - The user (or attacker) changes the ID:
-
GET /api/invoices/1002 - The server returns invoice
1002even if it belongs to someone else.
The “direct object reference” can be many things:
- Numeric IDs (/users/42)
- UUIDs (/docs/550e8400-e29b-41d4-a716-446655440000)
- Filenames/paths (/download?file=payroll.xlsx)
- Nested object IDs (/orgs/10/projects/99/issues/7)
Important nuance: Using UUIDs or “unpredictable” IDs does not fix IDOR. It may reduce casual guessing, but it’s still broken authorization if the server doesn’t enforce access rules.
Why IDOR keeps appearing
IDOR is common because it’s easy to accidentally ship when: - Developers implement authentication early, but authorization is added later or inconsistently. - Teams rely on UI constraints (“users can’t click that”) instead of server enforcement. - Microservices and APIs grow quickly, with many endpoints and inconsistent policy checks. - Access control is implemented per-endpoint manually instead of centrally.
What it looks like “on the wire”
Common IDOR request patterns include changing a path parameter, query parameter, or JSON field.
GET /api/v1/profile?user_id=123 HTTP/1.1
Authorization: Bearer <token>
Change user_id=123 to another value.
PUT /api/v1/shipping-addresses/8812 HTTP/1.1
Authorization: Bearer <token>
Content-Type: application/json
{"address":"...", "city":"...", "postal_code":"..."}
If the server doesn’t confirm you can edit address 8812, it’s an IDOR with write impact.
Quick verification with curl (authorized testing only)
In a test environment (or with explicit authorization), validate access control by replaying the same request with a different object ID:
# Baseline request for your own object
curl -sS -H "Authorization: Bearer $TOKEN" \
"https://app.example.com/api/invoices/1001" | jq .
# Attempt to access a different object
curl -i -H "Authorization: Bearer $TOKEN" \
"https://app.example.com/api/invoices/1002"
Signs of IDOR:
- 200 OK with another user’s data
- 204 No Content on delete requests you shouldn’t be able to perform
- 200 OK on update requests that modify objects you don’t own
What you want to see instead:
- 403 Forbidden (authenticated but not authorized)
- Or 404 Not Found if the app intentionally avoids confirming existence (authorization must still be enforced)
What to fix (server-side object authorization)
The fix is not “hide the ID.” The fix is: enforce authorization on every object access.
A minimal, common pattern (pseudocode):
invoice = db.get_invoice(invoice_id)
if invoice.account_id != current_user.account_id:
return 403
return invoice
In larger systems, prefer centralized policy enforcement (middleware, service layer checks, policy-as-code) so you don’t rely on every handler getting it right.
Where you’ll see IDOR in real systems
You’ll most often run into IDOR in applications where there are many “objects” owned by different users, customers, or tenants, especially when those objects are accessed via predictable identifiers.
Common real-world scenarios
- SaaS multi-tenant apps: viewing other customers’ tickets, invoices, or user lists by changing
tenant_id,org_id, or resource IDs. - APIs used by mobile apps: mobile endpoints often expose object IDs plainly; if backend checks are weak, IDOR appears.
- Customer portals: order histories, shipping details, statements, claims—any “my account” style resource.
- Document/download features:
download?documentId=orfile=parameters that allow access to other users’ files. - Admin-ish endpoints accidentally exposed to users: endpoints intended for support staff but reachable with normal user tokens.
- GraphQL APIs: querying nodes by ID and receiving data without enforcing field/object-level authorization.
Operational indicators (for defenders)
IDOR exploitation may show up as unusual access patterns, especially in APIs:
- Many sequential IDs requested rapidly (enumeration):
/api/orders/10001,/api/orders/10002,/api/orders/10003…- Repeated
403/404interspersed with occasional200on different object IDs - A single user accessing objects across many accounts/tenants
Log patterns to watch
If you log request paths and authenticated user identifiers, you can build detections like: - High cardinality of object IDs per user per time window - Requests to resources outside the user’s normal tenant/account scope
Example (illustrative) log fields to ensure you have:
- user_id / subject
- tenant_id (resolved server-side)
- resource_type and resource_id
- decision (authorized/denied) if you have a policy engine
A simple mental model to prevent IDOR
If your app uses any request that includes an object identifier—path, query, or body—ask:
“If I change this identifier to another valid one, will the server still authorize it?”
If the answer is “yes,” you likely have an IDOR/BOLA issue and should treat it as a high-severity access control defect.
Practical next steps for teams
- Inventory object-access endpoints: list every route that accepts an object ID and confirm an explicit authorization decision is made server-side.
- Centralize authorization: middleware/policy engines reduce the odds of “one missed endpoint.”
- Add automated tests: for each sensitive object, test “same user = allowed” and “different user = denied.”
- Monitor for enumeration: rate-limit and alert on unusual sequences of object IDs.
For nearby concepts you’ll see in appsec writeups, review what an IOC is and how it’s used in investigations: what is an ioc. If you’re building an API security program, it also helps to understand how IDOR/BOLA fits into broader attack chains like supply chain compromise: what is a supply chain attack.
Recommended tools (security hygiene that complements IDOR fixes)
IDOR is fundamentally a server-side authorization problem, but good security hygiene reduces blast radius and helps teams respond faster:
- For secure remote access during testing and incident response, consider a reputable VPN such as NordVPN: Check NordVPN pricing →.
- For password management and stronger account security in engineering teams, consider 1Password: Try 1Password →.
This article may contain affiliate links. We earn a commission on qualifying purchases at no extra cost to you.
Related terms
The broader category; IDOR is one common manifestation. Broken access control includes missing checks, incorrect role logic, forced browsing, and privilege escalation paths.
Common in API security to describe IDOR-style failures at the object level (e.g., “can I access this specific order?”). In many discussions, BOLA and IDOR are effectively the same class applied to APIs.
Authorization failures at the function/endpoint level (e.g., non-admin users can call /api/admin/export).
When an API accepts more fields than intended (e.g., {"role":"admin"}) and updates protected properties. Different from IDOR, but often appears alongside weak authorization.
Accessing unlinked or hidden endpoints directly. Can combine with IDOR when the hidden endpoint also lacks object checks.
Models used to implement authorization. IDOR indicates the model isn’t enforced consistently at the object access point.