Authorization Best Practices

Chapter 2 · Practice 4 of 4

Protect the indirect paths: files, search, exports and nested objects

From Object-level authorization: stop IDOR and BOLA

Why it matters

The main CRUD endpoints usually get checked. The leaks come from side doors:

  • Files and object storage. OWASP's cheat sheet says static resources and cloud buckets need access control matched to the data's sensitivity. Serve private files through short-lived signed URLs generated after an authorization check, and keep buckets private.
  • Search and autocomplete. A search index built from all tenants' data must filter by the caller's access, or the suggestions list becomes a data leak.
  • Exports and reports. "Download all" often runs a separate query path written months later.
  • Nested and related objects. POST /projects/12/tasks with assigneeId: 77: is user 77 in project 12, and may the caller assign them? Is project 12 yours at all?
  • GraphQL. Each resolver needs its own check, because a query can reach an object through any relationship.
  • Caches. A cached response keyed only by URL can serve one user's data to the next.

When you add a feature, list every way it can read or write data and confirm each one goes through the same scoped access layer.

Do

  • Generate signed file URLs only after an authorization check, with short expiry
  • Filter search results by the caller access before returning them
  • Validate that referenced IDs in a request belong to the same scope