Cross-app access: Identity Assertion JWT Authorization Grant (ID-JAG)
When an enterprise puts an agent host — ChatGPT Enterprise, Claude for Work, or an internal A2A fleet — in front of Devotel Orbit, the first question is not “which endpoint?” but “which credential, and who does it blame?” ID-JAG (the IETF Identity Assertion JWT Authorization Grant draft) is the emerging standard answer: your identity provider issues a signed assertion naming the end user, the agent host redeems it for a short-lived access token, and every call is attributable to both the user and the agent that made it. This page explains the model and maps each stage onto the Orbit primitives that already implement it; the step-by-step wiring lives in Set up cross-app access with ID-JAG-style token delegation.Section 1 — The problem: static keys can’t name a user or an agent
The default way to connect an agent host to an API is a static API key. That shape has three structural weaknesses for agent delegation:- The scope is wrong-sized. Agent hosts accumulate. A key minted for one workflow tends to get reused for the next, and ends up broadly scoped — a bearer whose compromise opens every surface it can reach, indefinitely.
- The token can’t say who asked. A static key names an integration, not a person. When an enterprise employee’s chat session drives the agent, the request Orbit receives is indistinguishable from every other request that host ever makes. Audit stops at “the agent host did something” — never “which user, through which agent.”
- Nothing expires on its own. Static keys live until someone rotates them. Delegation that began as a one-off task outlives the task by months.
Section 2 — The flow: IdP assertion in, bound access token out
ID-JAG (draft-ietf-oauth-identity-assertion-authz-grant) defines a three-party exchange:- The enterprise IdP issues an identity assertion. Your Okta, Auth0, or Microsoft Entra tenant signs a JWT that names the end user and the application the user is working through. The enterprise — not the API provider and not the agent host — is the root of identity.
- The agent host redeems the assertion. ChatGPT Enterprise, Claude for Work, or your own A2A coordinator presents the assertion to the resource server’s grants endpoint and receives a short-lived access token in return. The assertion is single-purpose: it exists only to be exchanged.
- The access token is bound to both parties. The returned token carries the end user’s identity (so the resource server can attribute and authorize per human) and the calling agent’s identity (so a fleet of agents sharing one enterprise can’t hide behind each other). It is scoped to what the delegation actually needs and expires in minutes.
Section 3 — Token binding, expiry, and how resource servers validate
Three properties make the redeemed token safe to trust:- Binding is in the signed payload. The user and agent identities
travel as claims inside the token’s signature. Tampering with either
invalidates the token exactly like any other claim — there is no
side-channel lookup to spoof. On the A2A path Orbit’s agent tokens carry
this as the standard
act(actor-chain) claim: the outermost entry is the nearest agent to the call, and walking the chain reaches the human principal accountable for it. - Expiry is structural, not procedural. The token carries
expand the verifier enforces it — a leaked token’s usable window is its remaining lifetime, nothing more. Orbit’s just-in-time credential broker clamps minted lifetimes to a hard ceiling of 300 seconds, regardless of what the caller requests. - Audience and scope are checked server-side. A resource server
validates the signature first, then
aud(the token must name the resource being called — a token minted for one audience never authenticates to another), then the scope claim against the specific action being attempted. On Orbit’s federated agent surface, an inbound bearer token whose audience isn’t the addressed agent, or whose scope doesn’t contain the skill being invoked, is rejected before any skill logic runs — and a present-but-invalid bearer never silently downgrades to a weaker handshake.
/public/.well-known/jwks.json on the API host — so a third party
can verify “this call came from tenant X’s Orbit agent, with these
scopes” with no shared-secret onboarding. The signed AgentCard a
federated agent serves advertises the bearer scheme (at+jwt, RFC 9068
profile) and that JWKS URI.
Section 4 — What exists on Orbit today, and how it maps to ID-JAG
The ID-JAG draft is still in progress at the IETF, and Orbit does not yet expose a literal “redeem an IdP assertion” endpoint. What ships today is the resource-server half of the model, in three primitives:- Authorization mandates — the control plane. A principal declares, per agent, what actions, tools, and data categories are allowed, with an invocation cap, an expiry, and a tamper-evident consent digest. Mandates can be delegated (attenuated — a child mandate can only ever narrow the parent) and revoked. This is where “the end user authorized this agent to do X” is recorded.
- Just-in-time credential minting —
POST /api/v1/agents/agent-authorization-mandate/credentialre-runs the exact same authorization gate against a declared intent (“agent X needs tool Y, for N seconds”) and, only when authorized, returns a single-scope bearer token whose lifetime is clamped to at most 300 seconds. The token names the agent as its subject and records the accountable principal in its actor chain. This is the shipped “assertion in, bound token out” stage: the mandate plus intent is the assertion Orbit consumes today. - RFC 9068 agent bearer tokens on A2A — federated agents accept
scoped OAuth2 profile tokens (
typ: "at+jwt", per-audienceaud, per-skillscope) as an inbound credential alongside the legacy HMAC handshake. This is the validation posture Section 3 describes, live on a public boundary.
Section 5 — Revocation, audit, and how this differs from API keys
Revocation is one action, not a hunt. A mandate is revocable (POST /api/v1/agents/agent-authorization-mandate/revoke) and terminal
— every subsequent gate check against it denies, and any token minted
from it dies within its 300-second ceiling regardless. Compare the API
key story: you revoke the key, but you first have to know which of the
host’s workflows hold a copy.
Audit names a person. Mandate issuance, every gate decision
(granted or denied), every credential mint, and revocation are each
audit-logged with the principal and agent identities — the same
accountability that travels inside the token’s actor chain. An API key’s
audit trail, by contrast, answers “the key did this”; a mandate-backed
token answers “user U, through agent A, did this.”
The two models are not mutually exclusive — subaccount API keys remain
the right credential for long-lived first-party integrations (messaging
workers, CDP pipelines, orchestration dashboards). The decision rule:
use API keys for your own services acting as themselves; use
mandate-backed short-lived tokens for an agent acting on a user’s
delegated authority. For the API key side of that split, see Choose
and scope API keys for messaging, CCaaS agents, and the
CDP; for the model underneath,
the authentication model concept page.
When the ID-JAG draft finalizes and IdP vendors ship assertion support,
expect the runbook’s IdP-side section to simplify — the Orbit-side
verification posture you build today is the same one the standard
assumes.