1. What Is It?
Broken Function Level Authorization happens when an API allows a user to execute a function that should only be available to a more privileged role.
The issue is not about whether the user is authenticated, and it is not primarily about which record they can access. The issue is whether they should be allowed to perform the action at all.
In the previous guide, we covered Unrestricted Resource Consumption and how attackers can abuse request cost. This guide focuses on a different question: even if the request is valid and authenticated, is the caller actually allowed to execute the function?
Read the API4 Guide2. Why It Matters
Broken Function Level Authorization is dangerous because:
- It exposes privileged capabilities to lower-privileged users.
- It often results in vertical privilege escalation.
- One missed role check can compromise an entire admin workflow.
- Attackers do not need to break authentication to abuse it.
In real-world systems, this can lead to:
- Unauthorized exports of sensitive internal data.
- User suspension, deletion, or moderation by non-admins.
- Access to billing, support, or management controls.
- Exposure of internal workflows and administrative secrets.
Why OWASP classifies it as API5
OWASP highlights this category because APIs often expose business, support, or administrative functions through clean, predictable routes. If role checks are missing or inconsistent, lower-privileged users can directly call functions that were meant only for administrators, operators, or internal staff.
3. How It Happens (Technical)
This issue appears when the API authenticates the caller correctly but does not enforce whether that caller’s role is allowed to invoke the endpoint.
In practice, this often happens when developers protect a route with “user must be logged in” logic and assume that is enough, even though the route is clearly administrative or privileged by purpose.
Common technical causes:
- Authentication is enforced, but role or scope checks are missing.
- Admin and non-admin routes share the same controller logic.
- Authorization is enforced in the UI, not in the API.
- Some privileged endpoints validate role, while others do not.
- New management routes are added without inheriting central policy.
Core Issue
api/admin_export.py# vulnerable
@app.post("/api/admin/export")
def admin_export(current_user=Depends(get_current_user)):
return app.state.export_payloadCorrect Direction
api/admin_export.py# safer
@app.post("/api/admin/export")
def admin_export(current_user=Depends(get_current_user)):
if current_user.role != "admin":
raise HTTPException(status_code=403, detail="Admins only")
return app.state.export_payloadKey concept: function-level authorization is about actions. The question is not “can this user see this object?” but “can this user execute this function?”
API1:
→ Wrong object
API3:
→ Wrong field
API5:
→ Wrong functionAttacker’s Perspective
From an attacker’s perspective, API5 is about finding routes that look administrative, operational, or internal and testing whether they are truly protected in the backend.
- Look for paths like /admin, /export, /moderation, /billing, or /internal.
- Ignore the frontend and call the API directly.
- Reuse a valid low-privilege token against privileged routes.
- Compare route behavior across different roles.
If a normal authenticated user can execute an admin-only action, Broken Function Level Authorization is present.
4. Real-World Example
This benchmark models a support platform API where a support user can directly access an administrative export function.
Relevant routes in the benchmark:
POST /api/auth/loginissues a valid token with a role claim.GET /api/mereturns the authenticated user profile.GET /api/ticketscorrectly restricts access to support/admin roles.POST /api/admin/exportis intended to be admin-only but skips the role check.
This contrast is useful because it shows the system is aware of roles, but fails to enforce them consistently on its most sensitive function.
Example endpoint:
POST /api/admin/exportExpected behavior: only users with the admin role should be able to call this function and receive export data.
Vulnerable Logic
api/admin_export.py@app.post("/api/admin/export")
def admin_export(
current_user=Depends(get_current_user),
):
# Intentional vulnerability:
# authentication is required, but admin role is not verified
return app.state.export_payloadWhat is wrong: the route requires authentication, but treats any authenticated user as trusted enough to invoke an administrative function.
Example attack flow:
- Login as the support user
[email protected]. - Obtain a valid bearer token.
- Call
POST /api/admin/exportdirectly. - Observe that privileged export data is returned instead of
403 Forbidden.
Result: a lower-privileged support user executes an admin-only export and receives sensitive data that should only be accessible to administrators.
Common Variations
- Hidden Admin Endpoints: routes are not visible in the UI, but remain callable directly.
- Method-Based Gaps: GET is protected correctly, but POST, PUT, PATCH, or DELETE are not.
- Inconsistent Role Enforcement: some management routes validate role while similar ones skip the check.
- Operational Control Exposure: export, moderation, billing, support, or internal maintenance functions are reachable by normal users.
5. How To Prevent
1. Deny privileged functions by default
Sensitive actions should require explicit permission. Do not assume that authentication implies permission to execute privileged operations.
2. Enforce role or permission checks at the endpoint
Every privileged function should validate required role, scope, or permission before performing any action.
authz/require_admin.pydef require_admin(user):
if user.role != "admin":
raise HTTPException(status_code=403, detail="Admins only")3. Separate administrative and regular routes clearly
Admin controllers and operational handlers should be isolated and inherit stronger authorization rules automatically.
4. Centralize function-level authorization
Use middleware, decorators, or policy helpers so new endpoints do not silently miss privileged role enforcement.
5. Audit every privileged non-read action
Export, moderation, deletion, billing, support overrides, and role changes should be reviewed explicitly. These functions are often where API5 appears.
Key Principle
- Authentication is not authorization
- Every privileged function needs an explicit gate
- Deny by default, then grant intentionally
- Protect the API route, not just the UI path to it
6. Detection Tips (Scanner Perspective)
Detecting API5 requires testing which functions are reachable by which roles, not only whether the endpoint exists.
Common techniques:
- Enumerate admin-looking and management-looking endpoints.
- Replay privileged actions with lower-privileged accounts.
- Compare behavior across support, member, and admin roles.
- Test all HTTP methods, not just GET.
- Ignore frontend restrictions and call the API directly.
Key signal: if a lower-privileged user can invoke an action intended for admins or internal roles, Broken Function Level Authorization is present.
7. Final Takeaway
Broken Function Level Authorization is about actions, not records.
It exists whenever:
- A privileged endpoint is reachable by the wrong role.
- Authentication is treated as sufficient for admin functions.
- Role checks are missing or inconsistent.
- Administrative actions are callable without explicit authorization.
Every privileged route should answer: Is this caller explicitly allowed to execute this function?
If the answer is not enforced at the endpoint, the API is exposed.