Blog
AppSec Blog

How to test for broken function-level authorization (BFLA) in APIs

 - 
June 25, 2026

Broken function-level authorization (BFLA) is one of the most serious API security vulnerabilities because it allows users to perform actions they were never intended to perform. Instead of exposing someone else’s data as with broken object-level authorization (BOLA), a BFLA vulnerability exposes privileged functionality such as approving payments, changing user roles, deleting records, or accessing administrator-only operations. For attackers, that often means moving beyond information disclosure to taking control of business-critical functions.

You information will be kept Private
Table of Contents

The challenge is that BFLA often hides behind functionality that appears to work correctly. Every endpoint may authenticate users successfully. Every request may return the expected HTTP status code. Even manual testing can miss some authorization flaws if testers don’t understand which functions should be restricted to which roles.

This makes systematic BFLA testing essential, with automation helping to reduce gaps once expected authorization behavior is defined.

Rather than checking endpoints one by one, effective BFLA testing starts by understanding the application’s functional model, mapping available user roles, and verifying that every privileged action is enforced consistently across every exposed API.

This guide presents a practical methodology and best practices for testing BFLA in REST and GraphQL APIs. It covers manual techniques used during penetration testing, discusses where automation can help, and explains how to build repeatable authorization regression tests into modern development pipelines.

Why BFLA testing is different from BOLA testing

Although BOLA and BFLA are closely related, they require different testing strategies.

BOLA asks a simple question: “Can this user access someone else’s object?” 

Take this example of fetching an order by ID:

GET /api/orders/4821

To check for BOLA, a customer can change the order ID to another user’s order and check whether the API returns data that should remain private. BOLA detection can often be automated using an API security scanner. 

BFLA asks a more complicated question: “Can this user perform a function reserved for another role?”

Instead of changing object identifiers, the tester changes who performs an operation. Take these examples of operations that should be admin-only:

POST /api/admin/users/4821/promote

or

POST /api/admin/users/4821/promote

If a standard employee can invoke administrative functions like promotion or product deletion simply because they know the endpoint exists, the API contains a broken function-level authorization vulnerability.

Many real-world privilege escalation attacks chain both vulnerabilities together. An attacker may first exploit BOLA to discover information about privileged users before using BFLA to invoke administrator-only functions.

Before you start: Prerequisites for effective BFLA testing 

Unlike many other API vulnerabilities, BFLA testing depends on comparing the behavior of multiple users performing the same operation. Before beginning the assessment, make sure you have access to a test environment set up with accounts that represent each privilege level within the application.

Requirement Why it’s needed
Guest account (if supported) Establishes baseline unauthenticated behavior.
Standard user account Verifies normal user permissions.
Intermediate privilege account (support, manager, finance, etc.) Tests privilege boundaries between business roles.
Administrator account Reveals legitimate privileged functionality and provides expected behavior for comparison.
Test environment with representative data Allows state-changing operations to be verified safely.

For manual testing, an intercepting proxy such as Burp Suite or OWASP ZAP can be useful for capturing and replaying requests. API clients such as Postman, Insomnia, or simply curl help create repeatable test cases, while browser developer tools reveal API traffic generated by modern single-page applications.

For larger environments that contain hundreds of applications and APIs, automated API discovery and continuous security testing can help build a more complete inventory of exposed functionality and support repeatable authorization regression testing.

Whenever possible, begin by capturing an authenticated administrator session through your intercepting proxy while legitimate privileged tasks are performed. This allows you to:

  • Establish the expected behavior for privileged operations.
  • Help build a more complete function inventory because many administrative endpoints, workflow actions, and management APIs are only exercised by privileged users and may never appear in public documentation or standard user traffic.

Understanding what you’re testing

Before sending a single request, it’s important to understand how the application under test models permissions. Many APIs don’t expose authorization rules explicitly. Instead, permissions emerge from some combination of:

  • User roles
  • Group membership
  • Feature flags
  • Subscription tiers
  • Tenant boundaries
  • Workflow state
  • Ownership rules
  • Business policies

For example, an e-commerce platform might define roles such as:

Role Typical capabilities
Customer Browse products, place orders, manage personal account
Support View customer records, update shipping information
Inventory manager Modify stock levels
Finance Process refunds
Administrator Manage users, roles, system settings

A successful BFLA assessment verifies that every privileged capability remains inaccessible to every unauthorized role.

This sounds straightforward until real applications introduce overlapping permissions, temporary elevation, delegated administration, partner accounts, regional administrators, and feature-specific roles.

Testing becomes much easier if you first document how authorization is supposed to work.

Modern APIs increasingly combine role-based access control (RBAC) with attribute-based access control (ABAC). A user’s role is often only one input into the authorization decision. Permissions may also depend on tenant membership, resource ownership, workflow state, department, geography, licensing tier, feature flags, or temporary delegated privileges.

Before testing begins, identify every attribute that influences authorization decisions rather than assuming permissions depend solely on user roles.

The following workflow starts with understanding the application’s intended authorization model before moving into increasingly targeted testing techniques.

Step 1: Build a complete function inventory

One of the biggest reasons testers miss BFLA vulnerabilities is that they never discover the protected functions – and you cannot test what you don’t know exists.

Instead of immediately looking for privilege escalation, begin by identifying every callable function exposed by the application. Administrator traffic captured during the prerequisite phase is often the best starting point for this inventory because it exposes privileged operations that ordinary users never invoke. 

Potential sources of function information include:

  • OpenAPI and Swagger specifications
  • GraphQL schema introspection
  • API documentation
  • Browser developer tools
  • Mobile application traffic
  • Proxy history
  • JavaScript files
  • Automated API discovery
  • Previously captured traffic
  • CI/CD deployment artifacts

Also, remember that REST endpoints are only one possible source of functionality. Modern applications may also expose privileged actions through:

  • GraphQL mutations
  • Background management APIs
  • Internal microservice gateways
  • Administrative SPAs
  • Mobile-specific APIs
  • Versioned legacy endpoints

For example, an administrator dashboard may generate requests like:

POST /api/v2/admin/users/4821/disable

while a customer portal never references the same endpoint.

Attackers actively look for such hidden management interfaces because they frequently receive less testing than public APIs.

Don’t ignore HTTP methods

Many authorization failures involve the HTTP method rather than the URL. Consider this endpoint:

/api/users/4821

An application might correctly allow all authenticated users to execute a read operation:

GET /api/users/4821

but then fail to restrict operations like:

PATCH /api/users/4821
DELETE /api/users/4821
PUT /api/users/4821

Developers sometimes secure one operation while accidentally exposing another because authorization logic is attached to individual handlers rather than the underlying resource. For example, GET may correctly require only authentication with no role restrictions, but applying the same logic to PUT, PATCH, or DELETE means omitting role checks for the same endpoint. 

For every discovered endpoint, you should enumerate every supported method, including unexpected and less common ones. A good set to check is GET, POST, PUT, PATCH, DELETE, OPTIONS, and HEAD.

Note that OPTIONS requests and the Allow header can sometimes reveal which methods an endpoint supports, but many frameworks, API gateways, and reverse proxies either omit this information or return generic responses. If the server does not accurately advertise supported methods, probe common methods directly. Even when multiple methods are supported on the same resource, each should enforce authorization independently. 

Step 2: Create a role authorization matrix

Once you’ve identified available functions, the next step is mapping which users should be allowed to execute them.

This seemingly simple exercise dramatically improves testing coverage. Instead of randomly trying different accounts, create a matrix similar to the following:

Function Guest User Support Admin
View profile
Update own profile
Reset another user’s password
Change user roles
Delete users

The matrix then becomes the foundation for every authorization test.

For each function, consistently verify both successes for authorized roles and failures for unauthorized roles. Many testers focus only on the second condition, but confirming that authorized users continue to function correctly helps distinguish genuine authorization failures from broken implementations, expired sessions, or environmental issues.

Step 3: Test every privileged function from every lower-privileged role

With your matrix complete, begin executing requests using accounts representing each role.

Suppose an administrator legitimately performs a promotion operation like:

POST /api/admin/users/842/promote

The next step is straightforward – repeat the exact same request using every lower-privilege account:

  • Manager
  • Support
  • Regular user
  • Guest (if authentication is optional)

Avoid modifying the request in this first phase.

If the operation succeeds but shouldn’t, you’ve identified a classic BFLA vulnerability where the server never checks the caller’s role. If it (correctly) fails, continue testing.

Authorization implementations may contain inconsistent rules across similar endpoints. For example, one administrative action may correctly require administrator privileges while another relies only on authentication. Testing every privileged function individually remains essential because assumptions rarely hold across an entire API.

Step 4: Modify requests without changing business intent

If direct replay finds nothing, start varying how requests are made. Authorization filters often behave differently depending on headers, routing, or request format.

Useful variations include:

  • Changing API versions
  • Switching content types
  • Removing optional headers
  • Modifying URL case
  • Testing alternate routes
  • Replaying requests captured from another client
  • Switching between JSON and form-encoded bodies where supported

Say the promotion operation from before correctly rejects a regular user:

POST /api/admin/users/842/promote

You can try variations like a different API version:

POST /v1/users/842/promote

or a different route:

POST /internal/users/842/promote

One of those may unexpectedly succeed if an older route uses different middleware. Such inconsistencies commonly appear after API refactoring or version migrations.

Rather than treating endpoints independently, think in terms of application functions. If there are three different ways to perform the same administrative action, every path deserves separate testing.

Look for privilege escalation through mass assignment

Some applications automatically bind request body fields directly to backend model properties. If privileged attributes are not explicitly protected, attackers may be able to modify values that should never be user-controlled.

For example, you might add a privileged field to a profile update request:

PUT /api/users/me
{
  "displayName": "Alice",
  "role": "admin"
}

The goal is not simply to inject unexpected fields, but to determine whether the application accepts changes to typical security-sensitive properties such as role, permissions, isAdmin, accountType, or feature flags without enforcing appropriate authorization.

Mass assignment becomes a BFLA vulnerability when the fields that can be modified influence authorization decisions, such as user roles, permission levels, account types, or administrative flags. Allowing users to overwrite non-security-critical fields such as display names or preferences may still be an application flaw, but it is a separate issue. During authorization testing, focus on whether mass assignment allows users to gain capabilities they were never intended to have.

Test JWT role and permission claims

If the application uses JWTs for authentication, inspect the claims they contain and determine which ones influence authorization decisions. During testing, look for tokens that include role- or permission-related claims such as:

{
  "sub": "12345",
  "role": "admin",
  "permissions": ["users:delete"]
}

If you can modify, replace, or replay a token containing elevated claims and the application grants additional privileges without independently validating those claims, you’ve likely identified a BFLA vulnerability. As with mass assignment, the key question is whether client-controlled data can influence server-side authorization decisions.

Step 5: Test complete workflows, not just individual endpoints

Many BFLA vulnerabilities only appear after several legitimate operations have already taken place. For example, suppose administrators can approve expense reports through this endpoint:

POST /api/admin/expenses/842/approve

Testing this endpoint directly is useful, but it may not expose the actual weakness.

Instead, consider the entire workflow:

  1. A regular employee creates an expense report.
  2. A manager reviews it.
  3. Finance approves payment.
  4. An administrator performs final authorization.

Now ask questions such as:

  • Can a standard employee skip directly to the approval step?
  • Can a manager perform administrator-only actions?
  • Can users repeat actions that should only happen once?
  • Can requests be replayed after the workflow has completed?
  • Can users execute functions after changing the workflow state?

Many APIs correctly protect individual endpoints while failing to validate whether the requested action makes sense at the current stage of the business process.

Instead of thinking in terms of endpoints, think in terms of state transitions. For every privileged action, ask: “Should this user be allowed to move the application from its current state to the next one?” If the answer is no, every possible transition should fail consistently.

Step 6: Look for hidden administrative functionality

Attackers rarely begin by guessing administrator endpoints at random (though common and default routes may provide a headstart). Instead, they collect clues from the application itself. Useful sources of information include:

  • JavaScript bundles
  • Frontend route definitions (React Router, Angular routing modules, Vue Router, etc.)
  • Generated API clients
  • Browser developer tools
  • Mobile applications
  • GraphQL schema metadata
  • OpenAPI specifications
  • Generated SDKs and client libraries 
  • Archived API documentation
  • Error messages
  • Version-control artifacts
  • Exposed configuration files

Modern single-page applications often expose administrative workflows long before they become visible in the user interface. Route definitions, generated client code, and observed network traffic frequently reveal endpoints that deserve additional authorization testing, even if users cannot currently navigate to them through the application. 

Examples of administrative endpoints with predictable naming conventions may include:

/admin/
/management/
/internal/
/system/
/backoffice/
/dashboard/
/staff/

Versioning creates separate attack opportunities. Applications frequently introduce a newer API while leaving older versions operational:

/api/v1/admin/users
/api/v2/admin/users
/internal/admin/users

Developers may have updated authorization middleware for one version but overlooked another.

Similarly, don’t assume undocumented endpoints are inaccessible. An endpoint omitted from public documentation may still be callable if a client knows the URL. API discovery therefore becomes an important first step before authorization testing begins.

Modern API discovery methods can combine documentation, observed traffic, automated crawling, API specifications, and runtime analysis to build a more complete inventory of exposed functionality.

Step 7: Test GraphQL authorization separately

GraphQL changes how applications expose functionality, but it does not eliminate authorization problems.

In many GraphQL deployments, all queries, mutations, and subscriptions are routed through a single endpoint:

POST /graphql

The authorization decision therefore happens inside resolver logic rather than at the HTTP routing layer. For that reason, testing the endpoint itself provides little value. Instead, you should enumerate available operations.

GraphQL introspection is an excellent starting point for this when enabled, but many production deployments disable introspection as a defense-in-depth measure. If introspection is unavailable, you will need to derive the schema from published documentation, client applications, captured traffic, persisted queries, or other schema recovery techniques before beginning authorization testing. 

In keeping with the “promote user” operation examples from above, let’s look at a sample GraphQL query:

mutation PromoteUser {
  promoteUser(id: 4821)
}

Questions to ask when looking for BFLA opportunities with this operation:

  • Can lower-privileged users execute administrator-only mutations?
  • Are mutations protected independently of related queries?
  • Does introspection expose privileged functionality?
  • If introspection is disabled, can the schema be reconstructed from client applications or observed traffic?
  • Do subscriptions leak events intended only for administrators?
  • Are subscription authorization checks enforced per subscription rather than only during connection establishment?
  • Do nested resolvers apply authorization consistently?

Resolver-level authorization mistakes are one common pitfall because individual developers often implement checks independently. One mutation may verify administrative privileges while another relies only on authentication, so the only reliable approach is to evaluate every privileged mutation separately.

Subscription authorization also deserves separate testing. Some implementations correctly authenticate the initial WebSocket connection but rely on that connection-level decision for every subsequent subscription request. Each subscription should independently enforce authorization so that lower-privileged users cannot subscribe to administrator-only event streams after establishing an otherwise valid connection. 

Step 8: Verify authorization across tenants

Many enterprise APIs support multiple organizations within the same application in a multi-tenant setup. 

If tenant isolation is weak, role-based authorization alone may be insufficient. Consider a multi-tenant application where Alice is an administrator for Company A. Regardless of her role in Company A, she should still be unable to perform administrative actions within Company B.

Testing should therefore include additional tenant combinations. A simple multi-tenant test matrix might be:

User role Same tenant Different tenant
User Denied Denied
Support Allowed if expected Denied
Administrator Allowed Denied

Cross-tenant privilege escalation often occurs when applications correctly validate a user’s role but fail to verify the scope of that role. In addition to tenant identifiers, you should also test organization IDs, workspace IDs, customer IDs, project IDs, and any other values that define administrative boundaries. 

Authorization should always be evaluated against both the user’s privileges and resource ownership or tenancy. 

Step 9: Test for inconsistent authorization decisions

Authorization should produce consistent results regardless of how functionality is accessed. In practice, this is rarely true in all cases.

The same API action may be available through multiple interfaces, including:

  • Web interface
  • Mobile application
  • Partner API
  • GraphQL API
  • REST API
  • Legacy endpoints
  • Batch APIs

It’s common for developers to duplicate the same authorization logic across multiple implementations. Over time, the rules for each interface drift apart. You may find that one interface only checks administrator privileges, another only checks authentication, and a third checks nothing but assumes the client never exposes the feature.

Whenever multiple interfaces perform the same operation, compare their authorization behavior directly. If one interface blocks a request while another allows it, you’ve likely discovered an implementation inconsistency worth investigating.

Confirming suspected BFLA vulnerabilities

A successful HTTP response alone does not confirm a BFLA vulnerability. Before reporting a finding, verify that the requested operation actually bypassed the intended authorization controls.

Useful confirmation steps:

  • Confirm that the requested server-side state actually changed.
  • Verify the change using a second authorized account where possible.
  • Confirm that new privileged functionality became available to the lower-privileged user.
  • Rule out intentionally delegated administration or workflow-specific permissions.
  • Check audit logs where available, but treat them as supporting evidence and don’t rely on them for confirmation – missing or incomplete audit entries do not rule out a BFLA vulnerability.

Taking the time to confirm authorization failures reduces false positives and provides developers with clear evidence that the issue is both reproducible and security-relevant.

Automating BFLA testing

Authorization testing has traditionally been considered difficult to automate because scanners struggle to understand business roles – and this is partly true.

Automation is most effective once expected authorization behavior has been defined. Security tools can repeatedly execute the same operation using multiple identities, compare behavior across releases, detect newly exposed endpoints, and identify unexpected authorization changes. But determining whether an operation should be permitted in the first place still requires an understanding of the application’s intended authorization model. 

Once expected permissions have been defined, automation can eliminate much of the repetitive work involved in regression testing. Good candidates for automation include:

  • Replaying requests across multiple authenticated roles
  • Verifying expected HTTP responses
  • Detecting newly exposed endpoints
  • Comparing authorization behavior across API versions
  • Exercising documented OpenAPI operations
  • Monitoring changes in application behavior after releases

Automation is especially valuable after developers modify authorization middleware, introduce new APIs, or migrate functionality between services.

Rather than rediscovering every authorization rule during each assessment, automated regression tests continuously verify that previously protected functionality remains protected.

Manual testing remains essential whenever authorization depends on complex business rules, temporary delegation, financial approvals, workflow state, or organizational policies that cannot easily be inferred from API responses alone.

Common mistakes to avoid during BFLA testing

  • Assuming that authentication equals authorization: Receiving a valid access token only proves identity. Every privileged function must independently verify whether the authenticated user is allowed to perform the requested action.
  • Testing only the user interface: The user interface often hides functionality that remains fully accessible through the API. Always test the API directly rather than relying on visible controls.
  • Focusing only on administrator accounts: Testing should involve every role. Many privilege escalation paths occur between intermediate roles rather than between users and administrators.
  • Ignoring workflow state: Authorization decisions frequently depend on business context. Requests that fail during one stage of a workflow may succeed unexpectedly during another.
  • Assuming one successful check secures every endpoint: Authorization implementations are rarely centralized. Testing one administrative function tells you little about the next one. Evaluate every privileged capability independently.

Manual testing and automated testing work best together for BFLA

No single approach can reliably identify every single BFLA vulnerability. 

Manual testing provides the contextual understanding needed to identify privilege boundaries, unusual workflows, and business-specific authorization rules. Automation provides consistency, repeatability, and broad coverage across large and rapidly changing API estates.

The strongest API security programs combine both approaches: manual assessments establish the expected authorization model, while automated testing helps ensure those expectations continue to hold as applications evolve through regular releases.

For organizations with large numbers of applications and APIs, automated API discovery and continuous security testing also reduce the risk of newly deployed endpoints escaping authorization testing altogether. Likewise, API-aware DAST provides an attacker’s-eye view of running applications, helping verify whether privileged functionality is actually reachable in deployed environments rather than relying solely on design assumptions. In a DAST-first application security program, this runtime perspective complements other testing techniques by focusing attention on exposed, exploitable attack paths instead of theoretical findings.

Common BFLA patterns and risk by industry

Although the testing methodology remains the same across different industries, the functions most likely to contain authorization flaws differ according to an application’s business purpose. Looking at common attack patterns and publicly reported authorization failures can help prioritize testing, particularly in large APIs where complete manual coverage may not be practical.

Financial services

Focus on payment approval, refund processing, credit limit changes, account administration, loan approval workflows, and fraud investigation tools. These operations often involve multiple business roles and complex approval chains that make inconsistent authorization more likely.

Pay special attention to bulk administrative operations such as transaction exports, payment approval queues, and settlement reporting. These functions often aggregate sensitive data or perform high-impact actions, making them attractive targets for privilege-escalation attacks. 

E-commerce

Prioritize inventory management, pricing changes, discount creation, refund approval, order cancellation, and merchant administration. Administrative APIs that support customer service or warehouse operations frequently expose privileged functionality that is never available through the customer-facing interface.

Healthcare

Test clinician-only operations such as prescription approval, patient record modification, appointment management, and insurance workflows. Many healthcare platforms combine role-based permissions with organizational boundaries and workflow state, making comprehensive authorization testing especially important.

Developer platforms

Look closely at repository administration, organization membership, access token management, deployment controls, build pipelines, and CI/CD administration. These environments often expose powerful management functions through APIs that are inaccessible from the standard user interface.

Several publicly disclosed authorization incidents affecting developer platforms have involved privileged repository operations, organization management, or deployment workflows becoming available to users outside their intended scope. For example, GitHub has disclosed authorization flaws that allowed unauthorized users to perform privileged repository operations, illustrating how function-level authorization failures can blur the boundary with object-level authorization. These cases reinforce the importance of testing what users are allowed to do, not simply which resources they can access.

Conclusion: Find BFLA before attackers do – manually and at scale

Broken function-level authorization is fundamentally a coverage and consistency problem. The vulnerability appears when an API exposes privileged functionality without consistently enforcing who is allowed to use it.

Finding BFLA requires more than replaying a few administrator requests. Effective testing starts with understanding the application’s authorization model, building a complete inventory of exposed functions, mapping permissions across every relevant role, and validating privileged actions across every interface, workflow, tenant boundary, and deployment.

Manual testing provides the context needed to understand what should be allowed. Automation makes that knowledge repeatable by continuously checking whether expected authorization behavior still holds as applications and APIs change.

For large API estates, that combination is the practical path forward: discover the functionality you expose, test it through authenticated roles, confirm suspected findings, and keep regression testing in place so new releases don’t reopen old privilege-escalation paths.

Invicti helps teams put that approach into practice with automated API discovery, API-aware DAST, and proof-based scanning that supports accurate, repeatable testing across modern web applications and APIs. 

Schedule a demo to see how Invicti can help you find and validate exploitable API security risks before attackers do.

Frequently asked questions

Frequently asked questions about BFLA testing

How do you test for broken function level authorization (BFLA)?

Testing for BFLA involves comparing how the same API function behaves when called by users with different privilege levels, from standard users through administrators. Start by building a function inventory and authorization matrix, then systematically test privileged operations, alternate routes, HTTP methods, workflows, and multi-tenant boundaries before confirming any suspected authorization bypasses.

What’s the difference between BFLA and BOLA testing?

BOLA testing checks whether a user can access objects that belong to someone else, while BFLA testing checks whether a user can perform functions reserved for a different role. In practice, BOLA focuses on object ownership and BFLA focuses on authorization to perform privileged actions, though real-world attacks often combine both vulnerabilities.

How do you confirm a suspected BFLA vulnerability?

A successful HTTP response alone does not confirm a BFLA vulnerability. Verify that the unauthorized operation actually succeeded, changed server-side state or exposed privileged functionality, and bypassed intended authorization controls rather than legitimate delegated permissions.

Can automated scanners detect BFLA?

Automated scanners can detect many BFLA vulnerabilities when they support authenticated, multi-role testing and compare authorization behavior across different user roles. However, they require the authorization model to be defined, so automation is most effective when combined with manually defined authorization expectations and continuous regression testing.

What are some real-world examples of BFLA vulnerabilities?

Publicly disclosed authorization flaws affecting platforms such as GitHub have demonstrated how unauthorized users can gain access to privileged repository operations that should be restricted to specific roles or permissions. These incidents highlight why authorization testing must verify what users are allowed to do, not just which resources they can access.

How does Invicti detect BFLA vulnerabilities?

Invicti helps identify BFLA vulnerabilities by combining API discovery with authenticated, API-aware DAST that tests exposed functionality from an attacker's perspective across different user contexts. Integrated into CI/CD pipelines, it supports repeatable authorization regression testing so newly introduced APIs and application changes can be assessed as part of the development process.

Table of Contents