API Security in Depth · Function Authorization, Abuse & SSRF

Broken Function Level Authorization

Deny-by-default route permissions and hidden admin endpoints.

BFLA: a regular user can call functions they shouldn't — admin endpoints, other roles' actions, or methods (DELETE where only GET was intended). Causes: authorization added per-handler (and forgotten), "hidden" endpoints assumed safe, and inconsistent checks between REST and GraphQL/gRPC paths. Fix with deny-by-default routing, declarative permissions per route, separate admin APIs (different host/auth), and a route inventory test that fails if any route lacks a policy.

BFLA anti-patterns

Pattern Risk Better
Admin endpoints on the public API Discoverable, same auth Separate admin API + network restrictions + step-up auth
Checks inside handlers Missed on new routes Route-level declarative policy
Allow by default New routes are open Deny by default
Role in request body Client-controlled Roles from token / server-side lookup
UI hides buttons API still callable Enforce in API
def test_every_route_declares_permission():
    missing = [r.path for r in app.routes
               if isinstance(r, APIRoute) and not getattr(r.endpoint, "__permission__", None)
               and r.path not in PUBLIC_ROUTES]
    assert not missing, f"Routes without a permission: {missing}"

def requires(permission: str):
    def deco(fn):
        fn.__permission__ = permission
        return fn
    return deco

Common pitfalls

  • Relying on obscure URLs for admin functions.
  • Different authorization in REST and GraphQL for the same operation.
  • Method confusion (PUT allowed where only GET is checked).

Key points

  • Deny by default
  • Declarative permission per route
  • Test that every route has a policy

Further reading: OWASP API5:2023 BFLA

Practice questions

How is BFLA different from BOLA?

Answer

BOLA is accessing an object you shouldn't (another user's order); BFLA is calling a function you shouldn't (an admin delete endpoint).

What automated test catches missing function-level authorization?

Answer

A test that enumerates all registered routes and fails if any non-public route lacks a declared permission/policy, plus role-matrix tests per endpoint.

Open in the app to mark lessons complete, take notes and track your progress.