Halloween DealsAmazon USHalloween week deals: useful picks before month-endAmazon US: current deals, useful picks and tech finds.Check DealsSlow PC?RecommendedPC slow today? Run a repair scan before it gets worseResolve common Windows issues and optimize system performance.Scan NowHalloween DealsAmazon USOctober picks are moving - compare before checkoutAmazon US: current deals, useful picks and tech finds.See Picks×
FREEDOM251

Freedom251 › Blog › API security

How BOLA Lets Predictable Employee IDs Reveal Other Records

By Freedom251 Team · · 8 min read

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Changing an employee ID should never reveal another employee’s record. If an API accepts an ID supplied by the client but does not check whether the signed-in caller may access that specific object, it has Broken Object Level Authorization (BOLA). Sequential or otherwise predictable IDs make it easier to try many references, but they are not the underlying security failure.

The employee-directory example in this article is a generic scenario, not a claim about a particular company or breach. The same defect can affect customer profiles, invoices, vehicles, documents, projects, exports and nested API resources.

As an Amazon Associate I earn from qualifying purchases.

What the employee-directory scenario looks like

Imagine an authenticated employee using a profile endpoint such as GET /api/employees/1842. The server returns that employee’s data because the request contains the number 1842. If the same session can change the number to 1843 and receive another person’s profile, the endpoint is making an object-level authorization decision incorrectly—or not making one at all.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The identifier is only a pointer to a record. Seeing it in a list, notification link, browser address, error message or mobile-app request does not grant permission to use it. Authorization must be evaluated for the authenticated principal, the requested object and the requested operation every time.

GET /api/employees/1843 HTTP/1.1
Authorization: Bearer <session-token>

A secure API might return the caller’s permitted profile, a deliberate 403 Forbidden, or a non-revealing 404 Not Found, depending on the application’s policy. What it must not do is return object 1843 merely because the caller guessed or obtained its identifier.

BOLA, IDOR and function-level authorization

Broken Object Level Authorization

OWASP uses BOLA for a missing or incorrect check on a particular object referenced by a request. The object can be identified in a URL path, query parameter, header, request body, GraphQL variable or another client-controlled field. The rule applies to every operation, not only profile reads.

Insecure Direct Object Reference

IDOR describes the familiar pattern in which a user changes a direct reference—such as an integer, UUID or filename—and reaches another user’s data. In API work, IDOR is closely related to BOLA; the practical lesson is the same: an identifier is not an access token.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Broken Function Level Authorization

BOLA is different from Broken Function Level Authorization (BFLA). BFLA occurs when a caller can invoke a function they should not be allowed to invoke at all, such as an administrator-only operation. BOLA occurs when the caller may use the general function but targets an object outside that caller’s permitted scope. An employee may be allowed to view their own profile while being forbidden to view a colleague’s profile.

Why predictable IDs make enumeration easier

Sequential numbers reduce the effort needed to discover references. An attacker who sees one valid ID can try nearby values, automate requests, or combine identifiers observed in normal application traffic. Random UUIDs and opaque strings make guessing harder, but they do not create authorization. A stolen or leaked UUID must still be rejected when the caller lacks permission.

Enumeration is an access pattern, not a separate authorization control. It becomes harmful when an endpoint accepts each altered reference without checking object ownership, tenant membership, role, relationship or another policy. A bulk endpoint can have the same defect even when no one guesses individual IDs: a request that asks for a list may return users or records outside the caller’s allowed scope.

Which operations need object-level checks?

Checking one successful GET request is not enough. Authorization can be inconsistent across methods, controllers and service layers. Review every path that reads or changes an object.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Operation or path What to verify Possible impact if unchecked
Profile or record GET The caller may read this specific employee or object Unauthorized disclosure of personal, employment or business data
PATCH or PUT The caller may change the referenced object and each editable field Data tampering, privilege changes or account compromise in some designs
DELETE The caller may remove this exact object Destruction of another user’s document, project or account data
Create or action requests containing an object ID Every referenced parent, owner or target is within scope Unauthorized assignment, sharing, transfer or other state change
Exports and downloads The export query is restricted to permitted objects, not just the download route Large-scale data disclosure
Nested resources Both the parent and child relationship are authorized Cross-tenant access through a valid child ID
GraphQL queries and mutations Resolvers authorize each returned or changed object Reading or deleting another user’s object through a mutation or resolver
Bulk and list endpoints Filters, pagination and submitted ID arrays are scope-limited Directory-wide or tenant-wide exposure without guessing each ID

How to test for BOLA safely

Test only applications and accounts for which you have explicit authorization. Do not enumerate a public employer directory or alter someone else’s data. A controlled two-account test reveals the authorization decision without putting real users at risk.

  1. Define the approved scope. Record the hostnames, endpoints, methods, test window and data-handling rules. Stop if the authorization does not clearly cover the test.
  2. Create two principals with different access. Use account A and account B, ideally in different tenants or with different ownership. Create or identify one object owned by each account.
  3. Capture a legitimate request. While authenticated as account A, use the documented API or authorized application traffic to request A’s object. Note every reference location, including path segments, query values, JSON fields and GraphQL variables.
  4. Change only the object reference. Send the same request as account A while substituting B’s object ID. Keep the method, token and other fields unchanged so the result isolates object authorization.
  5. Repeat for each method. Test reads, updates, deletes, downloads, exports and action endpoints where the scope allows. A denied read does not prove that an update or delete path is protected.
  6. Check nested and alternate representations. Try authorized nested routes, such as a project’s document endpoint, and GraphQL queries or mutations when those features exist. Confirm that the parent-child relationship is checked, not merely the child ID.
  7. Review list and bulk behavior. Determine whether account A’s list contains only permitted records. For bulk requests, verify that mixed arrays or filters cannot pull B’s objects into the response.
  8. Record the decision without collecting unnecessary data. Save request and response metadata, object ownership, status code and a minimal proof. Redact personal information and stop after confirming a flaw.

OWASP’s testing guidance also recommends looking at identifiers that another session can already observe in normal responses, errors or notification links. This is a way to assess authorization paths, not permission to guess at an unrelated service.

How to prevent IDOR and BOLA in an API

Enforce the decision on a trusted server

Perform the check in the API, gateway or trusted serverless layer. Hiding an employee ID in a web interface, disabling a button or checking permissions in JavaScript cannot protect the record because a caller can send the request directly.

Scope the data lookup itself

Prefer a query that combines the requested identifier with the caller’s permitted scope. Conceptually:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
object = repository.findOne({
  id: requestedId,
  permittedFor: authenticatedPrincipal
})
if object is null:
  return a non-revealing denial
return object

This is safer than retrieving any row by primary key and hoping a later serializer or controller notices that it belongs to another tenant. The permitted scope may be ownership, a tenant, a manager relationship, a project membership, a delegated role or a policy combining several attributes.

Authorize every operation and field

Apply object checks independently to reads, creates, updates, deletes, exports and actions. For writes, also validate which fields the caller may change. A user who can edit a display name may not be allowed to change a role, payroll field, manager or account status.

Cover every access path

Centralize policy logic where practical, but verify that all controllers, background jobs, download handlers, GraphQL resolvers, nested routes and bulk services invoke it. A secure top-level profile endpoint does not protect a second endpoint that returns the same object through a report or notification link.

Use least privilege and deny by default

Make the default outcome a denial unless a policy explicitly grants access to the requested object and operation. Avoid a role-only rule such as “employee can read employees” when the real requirement is “employee can read their own record and records in an assigned team.”

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Design bulk responses defensively

Apply authorization before assembling a list, export or search result. Do not accept a client-supplied array of IDs and then fetch all matching rows without filtering it through the caller’s scope. Pagination, sorting and search filters must not become alternate ways around the same policy.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

What identifier design can and cannot do

Approach Security value Limitation
Sequential numeric IDs Simple and efficient for databases Easy to guess; increases discovery attempts when authorization is missing
Random UUIDs or opaque identifiers Reduces casual guessing and automated enumeration Does not authorize access; a leaked or observed value remains usable unless the server checks permission
Client-side obscuring or hidden fields May reduce accidental exposure in the interface Provides no reliable protection against a crafted request
Server-side, object-scoped authorization Actually determines whether this principal may perform this operation on this object Must be implemented and maintained on every access path

Use non-sequential identifiers as defense in depth, alongside—not instead of—server-side policy enforcement.

Logging and detection

Authorization controls prevent access; telemetry helps you find inconsistent controls and investigate attempted abuse. Log the authenticated principal, endpoint, operation, object type, authorization outcome and correlation ID while minimizing sensitive values. Protect logs with the same care as application data.

Alerting can look for patterns such as one session requesting many adjacent identifiers, repeated denials across tenants, rapid changes to object references, or unusual bulk requests. Sequential-access patterns are useful investigation signals, but a lack of an alert is not evidence that authorization is correct. Logging should support review without storing full employee profiles or tokens.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Common fixes that fail

  • “The ID is hard to guess.” Guess resistance lowers discovery probability but cannot replace a permission check.
  • “The UI never shows that button.” An attacker can call the API without the interface.
  • “We check the user’s role.” A role may permit the function while saying nothing about the particular object, tenant or relationship.
  • “The read endpoint is protected.” Update, delete, export, nested, GraphQL and bulk paths may use different code and remain exposed.
  • “A 404 means it is secure.” A denial status can reduce information leakage, but the underlying query must still enforce scope. Test behavior, not only status codes.
  • “We will monitor it.” Detection is valuable for response, but it does not undo unauthorized disclosure or modification.

Developer and reviewer checklist

  • For each client-supplied object reference, can you name the server-side policy that authorizes it?
  • Does the lookup constrain results to the caller’s tenant, ownership or relationship before serialization?
  • Are read, create, update, delete, export and action methods covered?
  • Are nested routes, GraphQL resolvers, background jobs and bulk endpoints included?
  • Do field-level rules prevent a permitted object edit from becoming a privilege change?
  • Do automated tests use two principals with different scopes and verify both allowed and denied cases?
  • Are identifiers treated as untrusted input even when they are UUIDs or hidden from the interface?
  • Do logs provide enough context to detect repeated cross-object attempts without recording unnecessary personal data?

The decisive question is always: may this authenticated principal perform this operation on this particular object? If the API cannot answer that on the server for every path, predictable IDs can turn an ordinary reference into a directory-enumeration tool.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

API securityauthorizationBOLAEmployee DirectoryIDOROWASP

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Recommended PC Tool
Recommended PC Tool
Windows Errors? Fix Them Before They SpreadFree repair scan
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.