MastertheMesh
Blog · 2026-06-21

ID-JAG: enterprise identity finally catches up with AI agents

TO
Tom O'Rourke
EMEA Field CTO · Solo.io

A new IETF draft lets your identity provider broker an agent's access to a third-party tool, with no pasted keys and no per-tool consent box. It shipped for real this week. Here is what it does, the gap it leaves on purpose, and where the data plane picks it up.

ID-JAG (IETF draft) Cross-App Access Enterprise-Managed Auth MCP OAuth token exchange agentgateway

I'm a few weeks into Solo, and the thing that keeps coming up in customer conversations isn't the model or the prompts. It's identity. Not the IAM we've all run for years, identity for the agents themselves. So when an OAuth draft I'd been half-watching, ID-JAG, shipped across Anthropic, Claude, VS Code and Okta on the same day (18 June), I stopped half-watching and read it properly. Here's what it does, and the bit it leaves open.

Karl McGuinness, who was Okta's Chief Product Architect and co-wrote the draft with Aaron Parecki and Brian Campbell, called it the turning point. His LinkedIn post is the platform view. This is the plumbing view, what's actually on the wire and where it runs out.

This isn't a new RFC just yet. It's an IETF Internet-Draft at revision -03.

What options do we have?

I spent years on regulated platforms before Solo. FedRAMP, IL5, the sort of place where every credential has a paper trail and an auditor attached to it. When an agent acts for you inside another tool, Claude reaching into Asana, an SRE agent poking GitHub, it has to prove it's allowed. There are really three ways to do that, and until this draft only one of them was any good.

  1. Static credentials. API keys and long-lived tokens pasted into a config file, never expiring, with nobody tracking who holds them. The NSA's May 2026 advisory on MCP named exactly this, hardcoded credentials and long-lived personal tokens, as an unmanaged attack surface. Bad.
  2. Interactive OAuth consent. You personally click "allow" for each tool. Fine for one person at one keyboard, hopeless once an agent fans out across twenty tools at machine speed, and worse across a whole company. This and the keys both assume a human is present and setting the pace. Take the human out and neither holds up.
  3. Token exchange (RFC 8693). A gateway takes the user's login and swaps it for a scoped, short-lived token for the tool, no static key and no per-tool click. That's what we do at Solo with the agentgateway STS, and have for a while. This is the one that holds up.

That third option is exactly what ID-JAG just turned into a standard, it's a profile of the same RFC 8693 token exchange. So for us this isn't new ground, it's the rest of the ecosystem catching up to something our customers are already running.

Introducing ID-JAG, XAA and EMA

This is where most people get tangled, so let me untangle it. Three acronyms are flying around and they are not three competing things. They are three levels of the same idea.

TermWhat it isPlain version
ID-JAGThe standard (an IETF OAuth draft)The signed grant itself. Not the final access token, but the thing you redeem to get one.
XAAThe pattern (Cross-App Access)One app reaching into another, brokered by the identity provider. Okta's name for using ID-JAG.
EMAThe feature (Enterprise-Managed Authorization)The switch inside MCP and Claude that turns this on for a whole organisation, set once by an admin.

The order that helps: ID-JAG is the standard, XAA is the pattern, EMA is the product feature that flips it on. Get those three the right way round and the rest of the writing on this subject stops being confusing.

What shipped on 18 June

On 18 June 2026 this stopped being a draft people talked about and became a thing you can switch on:

MCP has sat under the Linux Foundation's Agentic AI Foundation since December 2025, and XAA was folded into the MCP spec as the Enterprise-Managed Authorization extension. The live list of providers, clients and servers is moving weekly, so by the time you read this it will be longer.

The flow, end to end

It's a token exchange followed by a redemption. The agent never holds a long-lived credential, the user never sees a per-tool box, and it's five steps.

The grant in step 3 is audienced to the tool's auth server, so it is something to redeem, not a token to use. Step 4 is where that server still applies its own policy and mints its own token. One audit trail, at the IdP.
  1. The user signs in to the agent through the identity provider. The agent now holds an identity assertion, an OIDC ID Token or a SAML assertion.
  2. The agent does an RFC 8693 token exchange at the IdP, presenting that assertion and asking for an ID-JAG audienced to the tool's auth server.
  3. The IdP applies organisation policy and returns a short-lived, signed ID-JAG. Its aud is the tool's authorization server, which is the whole trick.
  4. The agent redeems the grant at the tool's auth server using the RFC 7523 jwt-bearer grant. That server applies its own local policy and mints its own access token.
  5. The agent calls the API with that token. It is short-lived, so removing the user from a group at the IdP cuts access everywhere at once.

Nobody hands out a key, nobody clicks a per-tool box, and the audit trail lives in one place. A few rules in the draft are worth knowing exist: the tool's auth server must reject the grant if the aud is not its own issuer or the client_id does not match the authenticated client; an ID-JAG is bound to one tool, so there is no replaying it down a chain of hops; and it is for confidential clients only. The draft is a constrained profile of the wider OAuth identity-chaining work, built on token exchange and the JWT bearer grant. If you know those two RFCs, none of this is new machinery, it is a new way to combine them.

It names the user, not the agent

This is the bit I find most interesting, and the bit the headlines skip. The grant reliably names the user it's acting for, that's the sub claim. What it doesn't pin down cleanly is which agent is doing the acting. The slot for that second name is the act claim, from RFC 8693.

And act nests. An act can contain its own act, so a chain of agents shows its full lineage in one token. The human is the root, and the actor chain hangs beneath it, most recent agent outermost, the first one deepest.

{
  "sub": "Tom",                       // the human, on whose behalf
  "act": {
    "sub": "Agent E",                 // the agent making THIS call now
    "act": {
      "sub": "Agent D",
      "act": {
        "sub": "Agent C",
        "act": {
          "sub": "Agent B",
          "act": { "sub": "Agent A" } // the first agent Tom kicked off
        }
      }
    }
  }
}
The whole delegation history travels in one token. You read it, instead of reconstructing it from five separate logs.

The container is real and the nesting works. What RFC 8693 doesn't define is the rules: how deep is allowed, how each actor proves it's the genuine next link, what stops an agent dropping a hop or stamping in a more-trusted name than it earned. And ID-JAG takes an actor token and an act claim but deliberately doesn't say how to validate or govern them. That's left to future profiles, including Karl's separate Actor Profile for Delegation draft, which starts classifying entity types like user, service and AI agent. I'm still getting across the finer points of that work, but the shape is clear enough to build on.

So the chain can go as deep as you like, with the human as the root, but depth without per-hop verification is lineage you can read, not lineage you can trust. That gap is the whole reason agent identity is interesting rather than decorative. Verifying it is enforcement work that has to happen where the hops physically cross, which is the gateway.

ID-JAG only covers the connect decision

ID-JAG settles whether an agent may connect to a tool, for a given user. It says nothing about what the agent does once it is in. Those are two different questions, owned by two different layers, and keeping them apart is the thing that makes the whole picture click.

The grant gets the agent through with the user's identity attached. Per-tool policy still gates the actions. ID-JAG handing off the runtime half is not a weakness in the standard, it is a clean split, and the runtime half is where the interesting product work lives.

Where elicitation fits

ID-JAG and elicitation aren't rivals, they cover different situations. Today most of your tools aren't EMA-wired, simply because the capability only just shipped. So the deciding question is, does the IdP already broker trust to this tool, set up by an admin?

In Solo's agentgateway, elicitation is credential forwarding. Rather than minting a new token, the gateway runs a standard OAuth authorization-code flow between the user and the external provider, stores the resulting tokens, and injects them transparently into upstream requests. The agent itself never holds the external credential. You reach for it when the tool is not EMA-wired (most are not yet), when there is no enterprise IdP in play at all (a dev laptop, a lab), at first-time setup, or when policy deliberately wants a human back in the loop for a step-up.

Building it on a token-exchange data plane

Here's where it gets concrete if you run agentgateway and kagent. The thing that made it click for me: a token-exchange-native data plane already does the hard part. EMA mostly standardises, and puts an ecosystem name on, a flow the data plane was already running through token exchange.

Two key sets. The identity provider's JWKS validates what comes in. agentgateway's STS holds its own private key, signs the minted token, and publishes the matching public key at its own JWKS endpoint so the tool can validate what goes out. The STS is just another issuer from the tool's point of view.

agentgateway does not pass the inbound token through. The Security Token Service mints a new one, and you choose how much identity carries over. Impersonation mints a token that becomes the user, sub only. Delegation mints a token that carries both the user's sub and an act claim identifying the agent, nested across hops, so the downstream can inspect the chain and apply policy. Delegation is the mode you want for agents. In that mode the sub is preserved, the act is freshly stamped with the agent identity, the iss is rewritten to the STS, the aud is re-targeted to the downstream, and the claims your policy cares about, roles and groups and entitlements, pass through for the downstream to gate on. The walkthrough is in the agentgateway token-exchange docs.

A note for kagent specifically: almost nothing moves. The agent's own identity stays a SPIFFE workload identity, its SVID, which proves what the process is. The ID-JAG carries the user's delegated authority through the gateway to the tool, which is on whose behalf. Keep those two distinct, workload identity is not delegated authority. One change to be aware of: the older kagent-controller approach, where the controller signed tokens and exposed its own JWKS, has given way to the agentgateway STS as the home for the signing role. Same shape, different component.

What it doesn't solve yet

A post is only useful if it is honest about the edges. ID-JAG and EMA close the connect decision cleanly. They leave four things open, and every one of them is a data-plane responsibility.

  1. Agent-as-actor governance. The act claim exists, but validating it is deferred. "Which agent, acting for which human, verified" is unsolved at the standard level.
  2. Trustworthy multi-hop chains. No replay across hops is a good property. Per-hop attestation of the chain is enforcement work, not spec work.
  3. Action-time consent. EMA removes the standing consent screen at setup. It says nothing about "this agent is about to wire ten thousand pounds, confirm?" That mid-flight check lives in the data plane, gated by runtime policy.
  4. Attestation. ID-JAG assumes identity, it does not prove the workload. SPIFFE and per-hop signing do that, underneath.

That's the whole point, really. The standard does the boring half and leaves builders the interesting half.

Where Solo already fits

This is the part I'm closest to, so I'll be concrete. The thing that hit me coming out of the VMware lifecycle world is how much blast radius you hand an agent the second you give it tools, more than half your production services, with none of the guard rails you'd wrap around a normal workload. Look back at those four open items. Every one is a runtime job, and the runtime is what we build at Solo. We didn't build it for ID-JAG. We built it because customers needed delegated agent access before the front door had a standard.

The worry has it backwards. ID-JAG standardising the front door does not make a data plane less necessary, it makes the boundary clean. The IdP owns the connect decision. The gateway owns what happens after. The standard just drew a tidy line between the two, and we were already on the far side of it.

Is this the way forward?

The signals are about as strong as they get this early: standardising in the IETF, shipped on the same day across Anthropic, Microsoft and Okta, solving the single biggest blocker to enterprise MCP, and sitting under the Linux Foundation.

If you build or operate the apps that agents will reach into, here is what I would take away:

We've built the runtime half of this at Solo, because customers needed it before it had a name. So I'm glad the front door finally has a standard. It takes one argument off the table and lets us get on with the hard part, which agent is acting, and how you stop it when it shouldn't be.

I'm pulling this into a kind lab next, the brokered flow end to end on agentgateway, the delegation chain, and an AccessPolicy doing the runtime half. If that's useful to you, say so and I'll share the setup.

Sources: the ID-JAG draft (IETF OAuth WG), MCP Enterprise-Managed Authorization, Okta on Cross-App Access, RFC 8693 and RFC 7523, the agentgateway token-exchange docs, and Karl McGuinness's LinkedIn post. Compiled June 2026 and fact-checked against the draft. ID-JAG is an Internet-Draft, not a published RFC. Version-specific agentgateway paths should be re-verified against your installed release.