---
title: "Delegated authorization: Why acting on behalf of someone else is not a role"
description: "Delegated authorization explained. Why modeling on-behalf-of access as a role loses the subject, the approver and the expiry. Covers the RFC 8693 act claim, delegation versus impersonation, AuthZEN and COAZ, multi-party policy conditions, revocation before expiry, and audit lineage for delegated actions."
author: "Alex Olivier"
date: "2026-08-17T15:12:38.940Z"
canonical: "https://www.cerbos.dev/blog/delegated-authorization"
image: "https://stylish-appliance-1c1cc1c30d.media.strapiapp.com/Acting_on_behalf_of_someone_else_is_not_a_role_1_69fd5a51d1.png"
tags: ["guide"]
source: "https://www.cerbos.dev/blog/delegated-authorization"
---

# Delegated authorization: Why acting on behalf of someone else is not a role

*Delegation, just-in-time elevation and on-behalf-of access all break the assumption that the principal is the person doing the thing.*

Most authorization models assume the principal is the person doing the thing. A request arrives, you resolve an identity, you look up what that identity may do, and you answer. The assumption holds across most of an application and quietly fails for a large class of real work.

A support agent applies a billing adjustment above their normal limit because a supervisor approved it for one case. An engineer gets production access for the duration of an incident. An assistant books travel for an executive. In each of those, someone acts on behalf of someone else, under authority they do not normally hold, for a bounded window. The identity making the request is not the identity the request is about.

## Why a standing role cannot model delegated access

The instinct is to model this as a role. Mint something like `billing_adjuster_l2`, grant it when the supervisor approves, revoke it afterwards. That fails in three ways worth separating, because each fails at a different moment.

A role is standing. It exists until something removes it, and that something is a person or a scheduled job rather than a property of the grant. [Privilege creep](https://www.cerbos.dev/blog/privilege-creep-time-bomb-why-timely-access-review-is-critical) is the accumulated result of permissions that were all correct on the day they were issued.

A role is not scoped to a subject. Expressed as a role name, "may adjust this customer's bill" collapses into "may adjust bills", because a role carries no reference to the party it was granted for. The scope survives in a ticket or in nobody's head, and neither reaches the decision point.

A role loses the lineage. The record shows that the action was permitted and which identity performed it, not who authorised it, for whom, or on what grounds, because none of that was ever an input. That failure surfaces last, when somebody has to reconstruct why an unusual action was allowed and the only answer available is that the actor held the role at the time.

## How the RFC 8693 act claim carries delegation on the request

The better shape carries the delegation with the request rather than storing it against the identity. [RFC 8693](https://datatracker.ietf.org/doc/html/rfc8693) already defines the structure. The `act` claim, in the words of the RFC, "provides a means within a JWT to express that delegation has occurred and identify the acting party to whom authority has been delegated".

The RFC is careful about a distinction that matters here. Impersonation gives the acting party all the rights of the original and makes the two indistinguishable. Under delegation, "principal A still has its own identity separate from B, and it is explicitly understood that while B may have delegated some of its rights to A, any actions taken are being taken by A representing B". Impersonation erases the actor and takes the audit trail with it. Delegation keeps both parties visible.

A useful delegated token carries the subject it was issued for, the actor performing the request, the approver who granted the authority, and the instant the grant stops being valid. Expiry is not a detail. A short lifetime is the only part of this design that fails safe when everyone forgets to clean up. Deciding what goes into the token is itself an authorization decision, which is the argument for treating [token issuance](https://www.cerbos.dev/blog/tokens-are-authorization-decisions-a-guide-to-policy-driven-token-issuance) as policy-governed rather than as plumbing.

Getting the claims to the decision point is mechanical. Cerbos reads a signed JWT as [auxiliary data](https://docs.cerbos.dev/cerbos/latest/configuration/auxdata.html) and exposes its claims to policy as `request.auxData.jwt`, so the delegation travels the same path as any other attribute. Verification at the PDP is a precaution against tampering in flight, not an authoritative check, so the gateway or application should still verify the token first. Working with [token claims](https://www.cerbos.dev/blog/leveraging-jwt-claims-in-cerbos-access-control) directly avoids the step where a service flattens a rich token into one user ID.

## Writing policy conditions for actor, subject, approver and expiry

Once the claims arrive, the check stops being a lookup against one identity and becomes a conjunction over several parties. The policy can require that the actor holds the base capability at all, that the subject named in the grant is the customer this request touches, that the approver holds authority to grant that capability, and that the grant has not expired.

Each of those is an ordinary attribute [condition](https://docs.cerbos.dev/cerbos/latest/policies/conditions.html) once the data is present. Expiry compares against `now()`, a Cerbos extension to CEL. Subject scoping is an equality check between the customer ID in the grant and the one on the resource. The base capability suits a [derived role](https://docs.cerbos.dev/cerbos/latest/policies/derived_roles.html), since it depends on the relationship between actor and resource rather than on a static grant. All of it sits in the [resource policy](https://docs.cerbos.dev/cerbos/latest/policies/resource_policies.html) for the thing being acted on, beside the rules that govern the ordinary case.

What comes back matters as much as the yes or no. An expired grant, a grant issued for a different customer, and no grant at all are three situations that a bare deny collapses into one. [Policy outputs](https://docs.cerbos.dev/cerbos/latest/policies/outputs.html) return structured data alongside the effect, so the caller can say which requirement failed. That is the same reason to make denials [context aware](https://www.cerbos.dev/blog/making-application-authorization-context-aware-cerbos-outputs). A denial meaning "ask your supervisor" is not the same as one meaning "this is forbidden", and there is standards work in progress on that distinction which deserves its own treatment.

## Where AuthZEN and COAZ put the actor in a delegated request

The [AuthZEN Authorization API 1.0](https://openid.net/specs/authorization-api-1_0.html) reached Final Specification in January 2026 and standardises the protocol between the enforcement point and the decision point. Its information model is Subject, Action, Resource and Context, and the Subject is a single object with a required `type` and `id` plus optional `properties`. One subject.

That is a clean design, and it raises an honest question the moment a human, an agent and a delegation appear in the same request. Which of them is the subject. The working answer visible in the profiles is that the acting party is a set of related identities rather than one, spread across the subject, its properties and the context rather than expressed as more subjects.

[COAZ](https://openid.github.io/authzen/authzen-coaz-framework-1_0.html), a Standards Track draft from February 2026, describes a protocol-neutral way to project any protocol's information model into an AuthZEN request through declarative mapping, with expressions written by default in CEL. Its [MCP binding](https://openid.github.io/authzen/authzen-coaz-mcp-binding-1_0.html) takes the concrete route for agent tool calls. The authenticated human goes in the subject, and "for autonomous-agent use cases the `context` MUST include the agent identity". The binding says why plainly, that the separation "lets policies evaluate the trust level of the user and the agent independently". COAZ was drafted in the OpenID AuthZEN working group, where Cerbos is a contributor.

## AI agents acting on behalf of users are the same problem

An agent calling a tool on a user's behalf is structurally identical to a support agent applying an adjustment under supervisor approval. Two identities, one action, one bounded authority, and a decision that is wrong if it considers either identity alone. Delegation is being standardised now because agents made it impossible to ignore, but the pattern predates them and applies to human workflows running today.

Agents add pressure in one direction, because chains get longer. CoSAI's guidance in [Agentic Identity and Access Management](https://www.coalitionforsecureai.org/wp-content/uploads/2026/04/agentic-identity-and-access-control.pdf) is that authentication and authorization "MUST be enforced at each hop in an agentic chain and at the final enforcement point (tool, API, data system), not only at the initial gateway, to prevent confused-deputy and privilege-escalation issues". Confused deputy is exactly the failure delegation prevents, and it returns the moment one hop stops carrying the chain forward. Anyone building [agentic authorization](https://www.cerbos.dev/features-benefits-and-use-cases/agentic-authorization) or governing [non-human identities](https://www.cerbos.dev/blog/nhi-security-how-to-manage-non-human-identities-and-ai-agents) is solving this problem whether or not they call it delegation.

## Delegation depth, revocation and audit lineage

Delegation depth comes first. An actor can act for an actor. The `act` claim nests, and the RFC describes a chain where "the outermost `act` claim represents the current actor while nested `act` claims represent prior actors". Nothing in the format stops the nesting, so the cap is a policy decision. A policy that states no maximum has chosen unbounded depth by default, which is rarely what anyone intended.

Revocation before expiry comes second. A self-contained token cannot be un-issued, so a supervisor who withdraws approval two minutes later has changed nothing the token knows about. Two mitigations work together rather than as alternatives. Short lifetimes bound the exposure with no coordination. A lookup at decision time gives real revocation at the cost of a dependency on the decision path. Cerbos Synapse handles the second through [data sources](https://docs.cerbos.dev/synapse/latest/), which fetch attributes from an external system with caching in process or in Redis. Cache aggressively and you trade stale revocations for latency, cache lightly and you trade a dependency on the grant store for freshness.

The audit obligation comes third and is deferred most often. A delegated action needs the whole chain recorded, actor, subject, approver, grant reference and expiry, in the same record as the decision. A [decision log](https://www.cerbos.dev/blog/why-audit-logs-are-important) that captures only the effective principal is worse than none, because it looks complete. Months later it will report that the action was allowed and be unable to say why. Incomplete lineage on privileged actions sits alongside the other [blind spots](https://www.cerbos.dev/blog/5-authorization-blind-spots-auditors-find-and-how-to-fix-them) auditors reliably turn up.

## What delegated authorization changes in practice

None of this needs new machinery. It needs the delegation to survive the trip from approval to enforcement instead of being flattened into a role along the way. The token format has existed since 2020\. The protocol for delivering it to a decision point is now a final specification. The conditions that evaluate it are the same attribute comparisons you already write.

What changes is what the system can say afterwards. A model that keeps the actor, the subject, the approver and the expiry as separate inputs can answer who authorised an unusual action, for whom, and until when. A model that flattens them into a role can only answer that the actor held the role. Those two systems behave identically on a good day. They are not the same system on a bad one.

[**Try Cerbos**](https://hub.cerbos.cloud) to see how this works in practice, or [**book a call**](https://www.cerbos.dev/workshop) to talk through your architecture with the team.

**Go deeper:**

- [Securing AI agents and non-human identities in enterprises](https://solutions.cerbos.dev/securing-ai-agents-non-human-identities-in-enterprises) (eBook) for on-behalf-of access when the actor is an agent  
- [How to adopt externalized authorization](https://solutions.cerbos.dev/how-to-adopt-externalized-authorization) (eBook) for moving these decisions out of application code

## FAQ

### What is delegated authorization?

Delegated authorization is a model where the identity making a request is not the identity the request is about. Someone acts on behalf of someone else, under authority they do not normally hold, for a bounded window. A support agent applying a billing adjustment above their normal limit after a supervisor approves it is delegated authorization, and so is an engineer holding production access for the duration of an incident. Most authorization models assume the principal is the person doing the thing, and that assumption is what delegation breaks.

### What is the difference between delegation and impersonation?

The difference between delegation and impersonation is whether both parties stay visible. RFC 8693 describes impersonation as giving the acting party all the rights of the original so the two become indistinguishable, which erases the actor and takes the audit trail with it. Under delegation the acting party keeps its own identity separate from the party it acts for, and any actions taken are understood to be taken by the actor representing that party. If you need to answer later who authorized an unusual action, delegation is the only one of the two that can.

### Why is a role the wrong way to model on-behalf-of or just-in-time access?

A role is the wrong way to model on-behalf-of or just-in-time access because it fails in three separate ways. A role is standing, so it exists until a person or a scheduled job removes it, which is how privilege creep accumulates out of permissions that were all correct on the day they were issued. A role is also not scoped to a subject, so "may adjust this customer's bill" collapses into "may adjust bills" the moment it becomes a role name. And a role loses the lineage, because who approved the grant, for whom, and on what grounds were never inputs to the decision.

### What is the act claim in RFC 8693?

The act claim in RFC 8693 is the part of a JWT that expresses that delegation has occurred and identifies the acting party to whom authority has been delegated. A useful delegated token carries the subject it was issued for, the actor performing the request, the approver who granted the authority, and the instant the grant stops being valid. The claim nests, so the outermost act claim represents the current actor while nested claims represent prior actors in a chain. Deciding what goes into that token is itself an authorization decision, which is the argument for governing token issuance with policy rather than treating it as plumbing.

### What does a delegated authorization check need to evaluate?

A delegated authorization check needs to evaluate several parties at once rather than looking up one identity. The policy has to confirm that the actor holds the base capability, that the subject named in the grant is the customer this request actually touches, that the approver holds authority to grant that capability, and that the grant has not expired. Each of those is an ordinary attribute condition once the claims reach the decision point, and in Cerbos the base capability suits a derived role because it depends on the relationship between actor and resource. Returning structured outputs alongside the effect matters as well, since an expired grant, a grant issued for a different customer, and no grant at all are three situations that a bare deny collapses into one.

### How do you revoke a delegated grant before it expires?

Revoking a delegated grant before it expires needs something other than the token itself, because a self-contained token cannot be un-issued and a supervisor who withdraws approval two minutes later has changed nothing the token knows about. Two mitigations work together rather than as alternatives. Short lifetimes bound the exposure with no coordination, and a lookup at decision time gives real revocation at the cost of a dependency on the decision path. Cerbos Synapse handles the lookup through data sources that fetch attributes from an external system with caching in process or in Redis, so cache aggressively and you trade stale revocations for latency, cache lightly and you trade a dependency on the grant store for freshness.
