notes 2026-09-20 · 3 min read · updated 2026-09-20

API Authorization: BOLA, BFLA and Mass Assignment

Object and function level authorization, fields the client should never control, deprecated versions still running and what an OpenAPI schema does not prove.

API Authorization: BOLA, BFLA and Mass Assignment

API authorization bugs are boring to describe and expensive to have. They are also the ones a schema, a gateway and a linter all fail to catch.

API Mass Assignment and Property Authorization

When the backend maps an entire JSON document into a domain object, a field hidden from the UI may remain fully writable through the API. Mass assignment appears when automatic binding accepts properties beyond the intended allowlist. role, ownerId, approved, balance and tenantId are examples of properties that require their own authorization. I compare response schemas, update schemas and administrative objects to find fields the normal client never sends through the UI. Type validation does not replace authorization. A valid boolean is still dangerous when the user should not control that state.

1
2
3
4
PATCH /api/profile HTTP/1.1
Content-Type: application/json

{"displayName":"Gabriel","role":"admin"}

BOLA and IDOR

A long UUID is not authorization. If the backend does not bind an object to the correct identity, ID format only changes discovery difficulty. BOLA appears when a server accepts an object identifier without validating ownership or grant for the requested action. Identifiers appear in paths, bodies, headers, GraphQL nodes, nested objects and batch requests. I use two accounts, create equivalent objects and cross identifiers separately for read, update and delete. Access to a parent does not automatically grant access to every child. Authorization needs to follow relationships and the specific action.

1
2
GET /api/projects/0b1d... HTTP/1.1
Authorization: Bearer TOKEN_USER_A

BFLA

Hiding an administrator button solves the interface problem. The backend still needs to block the same function when a user calls the route directly. Broken Function Level Authorization appears when a normal role reaches an action reserved for another role. Method changes, alternate routes, old API versions and GraphQL mutations may expose the same function through another path. I compare traffic from a normal account and an administrator, then replay the smallest possible difference using the normal token. An endpoint missing from the frontend is not private. Server-side authorization should protect every function.

1
2
POST /api/admin/users/42/disable HTTP/1.1
Authorization: Bearer TOKEN_USER

API Versioning and Deprecated Endpoints

/v2 may be hardened while /v1 still accepts the same token under three-year-old authorization rules. APIs version through paths, headers, queries or media types. Old clients keep versions alive longer than teams expect. Deprecated endpoints may have different schemas, weaker authentication, old mass-assignment behavior and missing rate limits. I extract versions from mobile apps, JavaScript, documentation, DNS and errors, then compare the same action across versions. Removing documentation does not remove an endpoint. Decommissioning needs to happen in routing and backend code with visibility into remaining clients.

1
for v in v1 v2 v3; do curl -i https://api.example.test/$v/me; done

OpenAPI and Swagger

A public openapi.json may provide a perfect inventory. Risk appears in the endpoint the schema reveals and the backend protects incorrectly. OpenAPI describes paths, methods, parameters, schemas, security schemes and servers. Old schemas may reveal admin operations, internal hosts and deprecated fields. Generated clients also carry useful details. I import the spec, compare it with real traffic and flag operations unused by the UI for authorization and input testing. Exposing documentation is not automatically a vulnerability. The report should connect discovery to data or functions that should remain inaccessible.

1
curl -s https://api.example.test/openapi.json | jq '.paths | keys'

References

This post is licensed under CC BY 4.0 by the author.