Summary

  • draft-li-oauth-delegated-authorization-03 proposes a root-to-leaf chain in which an authorization server issues the root and a client may sign a narrower child token for another client. It is an individual Standards-Track Internet-Draft, not an RFC, consensus or deployment evidence.
  • A child signature proves that the key bound by the immediately preceding token signed the child. It does not prove that the root was trusted, that the chain stayed within its cumulative permissions, or that the resource owner approved this particular delegate.
  • The leaf client must present the exact ordered chain plus a DPoP proof. The resource server still validates every parent and adjacency, current status, claim-specific containment and its own operation policy before any application effect.

The shortest dangerous review of a delegation token is: “the signature is valid.” It is technically true and operationally incomplete. A client-issued token can be well formed, signed by the advertised key, bound to a fresh leaf key and still be unusable because the parent had no matching permission, because a deeper delegation was forbidden, because an ancestor was revoked, or because the resource server’s current policy refuses the operation.

draft-li-oauth-delegated-authorization-03 makes this dependency explicit. An authorization server issues a root Delegated Authorization Token. The root binds authorization to Client A’s key through cnf.jkt. Client A can exercise that authorization itself or, when delegation depth remains, sign a child token bound to Client B’s key. Client B can repeat the process only inside the authority left by the entire path.

The mechanism is attractive for agent systems and independently operated services because the authorization server need not approve every local hop. That absence is not a loophole. It is the design premise. The root decision pre-authorizes a bounded capacity to delegate, and each client may only attenuate it. The verifier recreates the authority from the trusted root, in order, at request time.

Revision 03 is work in progress. Its header states Standards Track intent, while the Datatracker API currently records no stream or intended-standard-level value. The text requests future media type, token type, authentication scheme, claim and metadata registrations. None of that is a current registry receipt, an implementation report or an assurance that the design will survive review unchanged.

The child’s key comes from the parent, not from itself

The root is different from every later token. It is signed under an authorization-server key obtained through trusted configuration or authenticated metadata. A resource server must not accept a root-supplied JWK merely because the token says who issued it. The first trust edge is external to the chain bytes.

For a client-issued child, the draft puts the delegator’s public JWK in the protected header. The verifier calculates that JWK’s RFC 7638 thumbprint and compares it with the parent’s cnf.jkt. It then verifies the child signature using the matching key. A successful pair says: the holder of the key that the parent authorized signed this child.

It does not say who that holder is in legal, organizational or workload terms. The means by which Client A obtains Client B’s public key and knows that it belongs to the intended delegate is outside the draft. A runtime, configuration channel or application protocol must supply that association. The token chain can preserve a key transition accurately while the onboarding process points to the wrong service.

That boundary matters during incident review. “Child signature valid” is a cryptographic receipt. “Key belonged to the intended payroll agent in tenant 41” is an identity-and-placement receipt. “The operator allowed payroll export” is an authorization receipt. Joining them into one green icon makes the unstandardized onboarding step invisible.

The verifier must also reject a client token as the first element. It cannot scan later elements for a root that makes the suffix work. Authority is directional. A valid signature in the middle cannot manufacture the trusted beginning it lacks.

Attenuation is a computation, not a slogan

The draft says a child cannot validly increase its parent’s authorization. That sentence sounds simple until permissions carry different semantics. scope can be treated as a set: every child value must already exist in the effective parent set. authorization_details is harder. Each registered detail type needs a semantic subset rule that understands resources, actions, wildcards, defaults, arrays and omitted members.

Raw JSON comparison is not enough. A shorter object can be broader because a missing field means “any.” Two details can share the same type while referring to different accounts or operations. An array can represent alternatives, conjunction or a bounded set depending on its definition. If a verifier cannot establish containment deterministically, revision 03 requires rejection.

Omission is also authority-bearing. If a child omits scope or authorization_details, that permission component disappears and may not reappear in a descendant. Audience behaves differently: omitting a child audience adds no new restriction, so the effective parent audience remains. Omitting nbf also adds no new lower time bound. Every extension claim must therefore define whether it can be introduced, reintroduced, inherited or discarded.

This is where a flexible token format can become a hidden policy institution. If implementers improvise containment for unknown claims, the common wire layer starts deciding which local semantics are “close enough.” The safer rule follows the doctrine in docs/heng-lu-note.md: keep common validation deterministic and thin. Unknown semantic expansion is not interpreted by a central service or guessed by a library. It is rejected locally until the relevant profile defines a reproducible rule.

The resource server must compute effective permission from the root through every child. It cannot validate each token in isolation and intersect whatever remains at the end. Claim omission, reintroduction and composition are path-dependent. The receipt is the traversal, not the leaf object.

Depth limits descendants, not damage by itself

Every root must carry a finite max_delegation_depth. If the effective parent value is m, an explicit child value must fall between zero and m-1; omission yields m-1. A zero-depth leaf may access a resource but cannot delegate again.

This creates a clean structural limit. It does not answer whether the selected depth is prudent. A depth of three can reach a vast number of descendants if each holder delegates widely. A one-hour token can support many actions. A narrow scope name can still control a high-value account. Chain depth limits the length of one proof path, not organizational blast radius, total verification work across requests or the number of issued siblings.

The draft therefore requires separate limits on token count, serialized size and verification cost. Leadership should add limits on fan-out, descendant inventory and task lifetime. A root issuer that records only “depth 4” cannot later enumerate which clients received children, because client-to-client issuance occurs without another authorization-server interaction.

That is the trade. Local delegation removes the authorization server from each hop, reducing latency and central dependence. It also removes a natural observation point. The system needs another receipt plane if incident responders must find every descendant. A log is evidence, not enforcement; lack of a log does not make a chain invalid under the draft, but it changes the recovery guarantee a deployment can honestly offer.

Delegation consent is not ordinary access consent

For grants involving a resource owner, revision 03 requires the authorization server to distinguish permission for protected-resource access from permission for client-issued delegation. Approval for an ordinary access token cannot silently become approval for Client A to authorize other clients.

The consent surface should disclose permissions, audiences, lifetime and maximum depth, and should not imply that the authorization server will observe or approve every child. That last point changes the principal’s risk. “Allow this client to read reports” and “allow this client to appoint other clients that may read reports” are not equivalent decisions even when the final resource scope is identical.

The root therefore carries two related powers: use and further delegation. The same bound private key can create a DPoP proof for present access or sign a child token when depth remains. Key compromise inherits both powers. A narrow signing interface should distinguish proof inputs from token-issuance inputs, because a generic signing oracle can turn a request-use compromise into a delegation compromise.

A client must not describe possession of the root as the resource owner’s approval of a particular delegate beyond what the chain encodes. The root can pre-authorize a class and depth of downstream choices. It does not prove the owner saw Client B’s name, workload, operator or exact later task. The delegator makes that localized choice and bears evidence for it.

This is a concrete authority boundary: the authorization server defines the maximum transferable envelope; the delegator selects a counterparty inside it; the resource server decides whether the resulting request is currently acceptable. None of the three may be collapsed into the others.

The exact order is part of the authorization

The proposed DA credential serializes compact JWTs from root to leaf, separated by ~. The resource server must reject an empty element, malformed token, excessive chain or changed order. The leaf DPoP proof’s ath value hashes the exact presented serialization. The verifier must not decode, normalize or reserialize tokens before that calculation.

Exact-byte binding prevents an observer from removing, adding or reordering elements in a captured request without a new leaf-key proof. It does not make every chain element valid. The resource server still verifies the root signature, every client signature, every cnf.jkt adjacency and every restriction. DPoP proves that the leaf holder authorized this request with these exact bytes; it does not retroactively authorize the bytes.

This is materially different from the existing BTW article on RFC 9449. DPoP owns sender constraint: possession of a chosen key, method and URI binding, proof freshness, replay handling and token hash binding. Revision 03 uses those mechanics as the final edge of a larger authority graph. Its distinctive work is preserving monotonic authorization across client-issued ancestors.

The draft also allows a subtle substitution property. A client-issued token contains no parent identifier. It can be valid in another chain when the immediately preceding token binds the same signing key and the cumulative restrictions encompass the child. One-token-one-key practice limits that portability; key reuse widens it. Exact-chain ath protects a presented request from mutation, but it does not prohibit the legitimate leaf signer from creating a fresh proof over another compatible chain.

If an operator requires one child to belong only to one specific parent chain, it needs distinct parent keys or an application-specific binding. A dashboard that labels a child JWT with one “parent ID” may therefore express a local inventory convention, not a property guaranteed by the proposed format.

Revocation is state distribution, not an endpoint response

Revision 03 extends the OAuth revocation endpoint to accept the complete exact chain and target its last token. The target’s bound-key holder or, for a client-issued child, its direct delegator can prove authority to revoke. Ordinary OAuth client authentication is not enough. A party that merely observed the chain cannot revoke it without an applicable private key.

The invalidation model is structural. Revoking the root invalidates every chain rooted there. Revoking a child invalidates every chain containing that child and all appended descendants, but it does not revoke the parent, siblings or another token bound to the same key.

The endpoint’s HTTP 200 is deliberately not a global completion receipt. It can be returned for successful revocation and invalid input. More importantly, accepted revocation records state at the authorization server. The draft defines no status-distribution mechanism to offline resource servers. An offline verifier can continue accepting a revoked ancestor until status reaches it or the token expires.

Prompt revocation therefore depends on a separate design: short lifetimes, introspection, synchronized status feeds or another promptly updated channel. Each resource server needs a currentness receipt identifying the status source, version or observation time it used. Without that, “revoked at 10:01” and “request accepted at 10:04” cannot be reconciled.

Incident responders should distinguish key revocation from token revocation. Destroying a compromised child private key prevents new proofs from that key if destruction is real, but signatures already made by an uncompromised parent remain valid objects. Conversely, revoking a child token requires every relevant verifier to learn the state. Neither operation alone proves termination of application sessions or derived credentials.

Resource authorization remains local

After all cryptographic and monotonic checks pass, the resource server still decides whether the effective authorization permits this operation. It applies scope, authorization details, audience, time and application claims together with resource-owner policy, tenant rules, resource state, revocation and other local controls.

The draft states the boundary plainly: a valid chain plus its bound private key does not guarantee access. A report may be locked for a legal hold. A tenant may disable exports. An account may have moved. A local risk rule may demand stronger confirmation. Those facts need not be encoded into every ancestor token to remain authoritative at the effect point.

This preserves localized future decision. The root does not become a remote command that forces every resource server to honor every syntactically contained child until expiry. It defines a ceiling. Each downstream token lowers that ceiling. The resource server can still choose a lower local floor or refuse the operation entirely.

The final application effect is another receipt. A 200 authorization decision can precede a database conflict, queue failure or partial external action. A retried request can duplicate an effect unless the application uses an idempotency or transaction mechanism. DPoP replay controls protect proof reuse within their acceptance model; they do not promise exactly-once business execution.

Ten receipts are better than one “delegation succeeded” event

Receipt Minimum evidence What it does not prove
Root consent Grant, separate delegation approval, maximum depth Approval of a named future child
Root issuance Issuer, root hash, audience, permissions, time, cnf.jkt Current resource access
Delegate association Intended workload, tenant, public-key thumbprint, channel That the child stayed in bounds
Child issuance Parent edge, child hash, restrictions, remaining depth Trusted root or current status
Chain validation Every signature, adjacency, containment and time result Leaf possession or local allow
Leaf proof Method, URI, exact-chain ath, nonce and replay result Valid ancestors or business intent
Status Ancestor status observations and freshness Delivery to every verifier
Local authorization Resource policy version, operation, decision Application commit
Effect Transaction/idempotency key and committed state Desired external outcome
Reconciliation Named observation and exceptions Authority for another action

The value of separation appears during failure. An invalid child does not require distrusting the authorization server. A revoked ancestor does not mean the leaf key was stolen. A valid chain denied by tenant policy is not a cryptographic failure. A committed operation with the wrong business result is not repaired by revalidating JWTs.

The article’s governing sentence is therefore narrower than “delegation without a central server.” The authorization server can be absent from child issuance only because its root bounded that absence in advance and the resource server later reconstructs every limit locally. The child token may be valid. Authority still belongs to the whole chain and the final decision point.