Broken access control has held the #1 spot on the OWASP Top 10 since 2021, and for good reason — studies show that the vast majority of tested applications contain some form of access control vulnerability. The typical cause isn’t a lack of authentication. It’s that authorization is too coarse. A user might have a valid JWT and the right role, yet the API still fails to check whether that specific user should access that specific resource.
Role-Based Access Control (RBAC) is a solid starting point, but modern APIs need more. When your system needs to answer questions like “Can this user edit this particular document?” or “Can this service read records belonging to this tenant?”, you need fine-grained authorization. And increasingly, teams are enforcing those decisions at the API gateway rather than scattering authorization logic across every backend service.
This article covers the evolution from coarse-grained RBAC to fine-grained authorization, introduces the OpenID AuthZEN standard that’s unifying how authorization decisions are made, and shows how you can implement these patterns at the gateway layer with Zuplo.
In this article:
- Why RBAC Isn’t Enough
- Understanding Fine-Grained Authorization
- What Is OpenID AuthZEN?
- Gateway-Enforced vs. Application-Level Authorization
- Implementing Fine-Grained Authorization with Zuplo
- The Future of API Authorization
- Getting Started
Why RBAC Isn’t Enough
RBAC works well for broad access decisions: admins can manage users, editors can update content, viewers can read it. You assign roles, check them at the API layer, and move on.
But RBAC starts to break down when your authorization requirements become more granular:
- Resource-level access: “Can user A edit document 42?” RBAC only tells you that editors can edit documents in general — not which ones.
- Contextual decisions: “Can this request proceed given the user’s department, the resource’s classification, and the time of day?” Roles don’t capture this context.
- Relationship-based access: “Can this user view this file because they belong to a team that owns the parent folder?” Role hierarchies can’t model arbitrary resource relationships.
These gaps are exactly what OWASP categorizes as Broken Object Level Authorization (BOLA) and Broken Function Level Authorization (BFLA) — vulnerabilities that exist even when authentication and basic role checks are in place.
Understanding Fine-Grained Authorization
Fine-grained authorization moves beyond “can this role access this endpoint” to “can this subject perform this action on this specific resource.” There are three main approaches.
Attribute-Based Access Control (ABAC)
ABAC evaluates policies based on attributes of the subject, resource, action, and environment. A policy engine might check that the requesting user’s department matches the resource’s owner department, or that the request originates from an approved network during business hours.
ABAC is sometimes called “policy-as-code” because the authorization logic lives in a policy language (like Rego for Open Policy Agent, or Cedar for AWS Verified Permissions) rather than in application code.
Relationship-Based Access Control (ReBAC)
ReBAC models authorization as a graph of relationships between subjects and resources. Instead of asking “does this user have the editor role?”, ReBAC asks “does this user have an editor relationship with this specific document?” This approach, popularized by Google’s Zanzibar paper, powers systems like OpenFGA and Okta FGA.
ReBAC excels at modeling hierarchical and inherited permissions — a user who owns a folder automatically gets access to documents within it.
Policy Decision Points (PDPs)
Both ABAC and ReBAC typically rely on a Policy Decision Point (PDP) — an external service that evaluates authorization requests and returns allow/deny decisions. The application or gateway acts as the Policy Enforcement Point (PEP), asking the PDP for a decision and enforcing the result.
This separation is powerful: your authorization logic lives in one place, and every service in your architecture can query the same PDP for consistent decisions.
What Is OpenID AuthZEN?
The challenge with fine-grained authorization has been interoperability. Every PDP vendor — whether it’s OPA, Cedar, Topaz, or a custom solution — has its own API for requesting authorization decisions. If you want to swap out your policy engine, you have to rewrite every integration point.
AuthZEN is a specification from the OpenID Foundation that solves this by defining a standard API for communicating with PDPs. Think of it as what OpenID Connect did for authentication, but for authorization. The Authorization API 1.0 specification defines a JSON-based request/response format that any PDP can implement:
- Subject: Who is making the request (a user ID, a service identity)
- Resource: What is being accessed (a document, an API route, a database record)
- Action: What operation is being performed (read, write, delete)
The PDP receives this standardized payload, evaluates it against whatever policy model it uses internally (RBAC, ABAC, ReBAC, or anything else), and returns a decision. Because the interface is standard, you can switch between policy engines without changing your enforcement points.
AuthZEN reached a significant milestone in early 2026 when the Authorization API 1.0 specification was approved as a Final Specification by the OpenID Foundation. Gartner has recommended that organizations “adopt standards like AuthZEN to reduce vendor lock-in and enhance interoperability” in their authorization infrastructure.
Gateway-Enforced vs. Application-Level Authorization
You can enforce authorization at two levels: in your application code, or at the API gateway. Each approach has trade-offs.
Application-level authorization
Authorization logic lives inside each service. The service extracts identity information from the request, calls a PDP (or evaluates policies locally), and decides whether to proceed.
Advantages: The service has full context — it knows the business domain, the data model, and can make highly specific decisions.
Disadvantages: Every service must implement authorization correctly. Authorization logic gets scattered across your codebase. A single missed check creates a vulnerability.
Gateway-level authorization
The API gateway intercepts requests before they reach your backend and makes authorization decisions at the edge. The gateway extracts identity context (from JWTs, API keys, or headers), constructs an authorization query, sends it to a PDP, and either allows or blocks the request.
Advantages: Centralized enforcement means no backend service can accidentally skip authorization. You get a single audit point for all access decisions. Policies can be updated without redeploying application code.
Disadvantages: The gateway may not have deep business context. Some decisions (like “can this user see this specific field in the response?”) might still need application-level checks.
The best approach: both
In practice, gateway-enforced authorization works best as the first line of defense. The gateway handles coarse-to-medium-grained checks — “is this user allowed to call this endpoint with this method on this resource type?” — while backend services handle any remaining fine-grained or business-specific logic. This layered approach ensures that even if a backend service has a bug, unauthorized requests never reach it.
Implementing Fine-Grained Authorization with Zuplo
Zuplo’s programmable API gateway supports fine-grained authorization natively, with built-in policies for the AuthZEN standard and other popular authorization systems.
Using the AuthZEN policy
Zuplo provides a built-in
AuthZEN Authorization Policy
that integrates directly with any AuthZEN-compatible PDP. You configure it in
your policies.json file with the PDP hostname and the subject, resource, and
action mappings:
The special $authzen-prop() syntax dynamically pulls values from the incoming
request or context — for example, $authzen-prop(request.user.sub) extracts the
authenticated user’s subject identifier from the JWT, and
$authzen-prop(context.route.path) uses the matched route path as the resource
ID.
When a request comes in, the policy constructs a standard AuthZEN authorization request, sends it to your PDP, and blocks the request with a 403 response if the PDP returns a deny decision.
Note: The AuthZEN policy is currently in beta and is available as part of Zuplo’s enterprise plans. It’s free to try on any plan for development purposes.
Programmatic control with custom policies
For more complex scenarios, you can set the authorization payload programmatically in a custom TypeScript policy that runs before the AuthZEN policy:
This custom policy runs first in the pipeline, enriching the authorization
context with domain-specific information. The AuthZEN policy then sends this
payload to the PDP. This pattern lets you combine Zuplo’s declarative
configuration with programmatic logic — start with the built-in
$authzen-prop() syntax for simple cases, and add custom policies when you need
richer context.
Other fine-grained authorization policies
Zuplo also offers built-in policies for other popular authorization systems:
- OpenFGA Authorization Policy — integrates with OpenFGA for relationship-based access control using Google’s Zanzibar model
- Okta FGA Authorization Policy — connects to Okta’s hosted Fine-Grained Authorization service for managed ReBAC
Like the AuthZEN policy, the OpenFGA and Okta FGA policies are currently in beta and available on enterprise plans. Each follows the same pattern: configure the connection to your authorization service, set the context checks (either declaratively or programmatically), and let the gateway enforce the decision.
Chaining policies for layered security
A common pattern is to chain authentication and authorization policies on a route. For example, you might verify a JWT first, then run an AuthZEN authorization check:
This pipeline first authenticates the user (ensuring request.user is
populated), then runs your custom policy to set the authorization context, and
finally calls the AuthZEN PDP to make the access decision — all before the
request ever reaches your backend service.
The Future of API Authorization
AuthZEN is part of a broader shift toward standardized, externalized authorization. Several trends are converging:
- AI agents and automated access: As agentic applications make autonomous API calls, the need for fine-grained, real-time authorization decisions becomes critical. An AI agent shouldn’t inherit blanket permissions from the user who deployed it — each action should be individually authorized.
- Zero-trust architectures: The principle of “never trust, always verify” extends naturally to authorization. Every API call should be evaluated against the current policy state, not against a static role assignment cached in a token.
- Authorization as infrastructure: Just as authentication moved from homegrown solutions to standardized identity providers, authorization is moving to dedicated PDPs with standard interfaces. AuthZEN accelerates this by ensuring your enforcement points aren’t locked into a single vendor.
The AuthZEN Working Group has outlined plans for deeper integration with frameworks like the Shared Signals Framework, signaling that standardized authorization is becoming a foundational layer of API infrastructure.
Getting Started
If your APIs currently rely on RBAC alone, here’s a practical path forward:
- Audit your authorization gaps: Identify endpoints where role checks aren’t sufficient — anywhere a user could access another user’s resources by manipulating IDs or parameters.
- Choose a PDP: Evaluate options like Topaz, OpenFGA, Cerbos, or Axiomatics. If you want vendor flexibility, prioritize PDPs that support the AuthZEN standard.
- Enforce at the gateway: Configure Zuplo’s AuthZEN policy to call your PDP on every request. Start with a few critical routes and expand from there.
- Layer your defenses: Use gateway-level authorization for broad enforcement and add application-level checks where you need deep business context.
Fine-grained authorization isn’t just a security improvement — it’s the foundation for building APIs that can safely serve multi-tenant applications, AI agents, and partner integrations. With standards like AuthZEN maturing and API gateways like Zuplo providing native enforcement, the barrier to adopting these patterns has never been lower.
Ready to enforce fine-grained authorization at your API gateway? Get started with Zuplo’s AuthZEN policy or explore the full suite of Zuplo authorization policies.