Skip to content
agentic ai

Enterprise-Managed Authorization: Cross App Access, ID-JAG, and CIMD for B2B SaaS

Updated · 13 min read · By

On this page

Key takeaways

  • Enterprise-Managed Authorization moves the 'may this agent reach this app for this user' decision from per-user consent screens to the customer's IdP.
  • Two layers: CIMD gives the agent a verifiable software identity (an HTTPS URL), and ID-JAG carries the IdP's per-user, per-app policy decision.
  • The flow is RFC 8693 token exchange at the customer IdP, then an RFC 7523 jwt-bearer grant at your authorization server.
  • Your SaaS reuses the SSO trust it already has with each tenant's IdP. The new work is validating ID-JAGs and issuing short, scoped tokens.
  • As of 2026-10-05 both IETF drafts are still drafts. Okta, Auth0, and Descope ship pieces of it. Verify everything in a POC.

This guide is for B2B SaaS teams whose enterprise customers now ask a new question. "Our employees use AI agents. Can those agents call your API or MCP server, under our IdP's rules, without every employee clicking through an OAuth consent screen?" The answer the market is converging on has three names and two specs. This page untangles them and lists what you have to build.

What Enterprise-Managed Authorization is

Three labels describe the same mechanism:

LabelWho uses itWhat it names
Identity Assertion JWT Authorization Grant (ID-JAG)IETF OAuth WGThe protocol and the token. draft-ietf-oauth-identity-assertion-authz-grant-04, 21 May 2026.
Cross App Access (XAA)Okta, also Descope and Auth0 in product docsThe product capability built on ID-JAG.
Enterprise-Managed AuthorizationMCP, Auth0's blogThe MCP extension io.modelcontextprotocol/enterprise-managed-authorization.

"Enterprise-Managed Authorization" as an industry-wide umbrella term is early. It is MCP's extension name, and Auth0 uses it too. Expect the vocabulary to keep moving. The wire protocol is what to anchor on.

The problem it solves

B2B SaaS apps already have three ways to let one piece of software reach another on a user's behalf. Each one breaks down when an enterprise brings AI agents.

Per-user OAuth consent sprawl. Every employee who connects an agent to your app runs an authorization code flow and clicks "Allow". The enterprise admin sees none of it. There is no central place to say "Agent X may reach App Y, read-only, for the finance group." Offboarding an agent means finding every grant.

Static API keys. The fallback when OAuth feels heavy. A key pasted into an agent config has no user binding, no expiry, and no policy behind it. Okta's Oktane 2026 announcement framed Agent SSO as exchanging exactly these non-expiring keys for short-lived, identity-governed tokens.

Dynamic Client Registration sprawl. Earlier MCP spec versions (2025-03-26 and 2025-06-18) leaned on Dynamic Client Registration. Every agent instance registers itself, so your authorization server accumulates clients it cannot identify. The MCP Server Identity Model guide covers how open DCR became the default risk.

None of these let the customer's security team apply the policy they already run for workforce SSO. That is the gap.

The two layers: CIMD and ID-JAG

Enterprise-Managed Authorization answers two separate questions. Keep them apart in your head and in your code.

Layer 1: which software is this? CIMD. A Client ID Metadata Document makes the OAuth client_id an HTTPS URL. That URL serves a JSON document describing the client: its name, its redirect URIs, its public keys. Any authorization server can fetch it. No registration call is needed. CIMD is draft-ietf-oauth-client-id-metadata-document-02 (6 Jul 2026). The MCP authorization spec dated 2025-11-25 says authorization servers and clients SHOULD support it. For the background on why CIMD replaces DCR in MCP, read CIMD: the future of MCP authentication.

Layer 2: may this software act for this user, here? ID-JAG. The customer's IdP evaluates admin policy and, if allowed, signs a short-lived JWT. That JWT names the user, the requesting client, and the target authorization server. WorkOS describes the IdP as "the policy enforcement point: it mints the assertion only if the admin's policy allows that requesting app to reach that resource app for that user."

The two layers connect at one claim. Per WorkOS, "a client_id inside the ID-JAG is a CIMD identifier." So the ID-JAG says who is acting, and the CIMD URL in it says which software is acting. Your authorization server checks both.

The flow, step by step

Four parties take part:

  • User: an employee of your enterprise customer.
  • Requesting app: the AI agent or app that wants to call your API. Its client_id is ideally a CIMD URL.
  • Enterprise IdP: the customer's identity provider. Your app already trusts it for that tenant's SSO.
  • Resource app: your SaaS. It has an authorization server (resource AS) and an API or MCP server (resource server).

Step 0: the user signs in to the requesting app

The user logs in to the requesting app through the enterprise IdP with OIDC (or SAML). The requesting app now holds an ID token for that user, issued by the IdP.

Step 1: token exchange at the IdP

The requesting app calls the IdP's token endpoint using RFC 8693 token exchange. It sends the user's ID token as the subject_token and asks for an ID-JAG aimed at your authorization server.

POST /oauth2/token HTTP/1.1
Host: idp.customer.example
Content-Type: application/x-www-form-urlencoded
 
grant_type=urn:ietf:params:oauth:grant-type:token-exchange
&requested_token_type=urn:ietf:params:oauth:token-type:id-jag
&audience=https://auth.your-saas.example
&resource=https://api.your-saas.example/mcp
&scope=tickets.read
&subject_token=eyJhbGciOiJSUzI1NiIsImtpZCI6...
&subject_token_type=urn:ietf:params:oauth:token-type:id_token
&client_id=https://agent.vendor.example/oauth/client.json

Illustrative request. Hostnames, scope, and token are placeholders. The requesting app also authenticates itself to the IdP using whatever method the IdP requires.

The parameters that matter:

  • grant_type: the RFC 8693 token exchange grant.
  • requested_token_type: urn:ietf:params:oauth:token-type:id-jag. This is what makes it an ID-JAG request.
  • audience: your authorization server's issuer identifier. The ID-JAG is only usable there.
  • resource: optionally, the specific API or MCP server the token is for.
  • subject_token: the user's ID token from the IdP. A SAML assertion is also allowed by the draft.

The IdP applies admin policy. It checks whether this requesting app may reach this resource app for this user, with these scopes. If not, it refuses. If yes, it mints an ID-JAG.

Step 2: the ID-JAG

The ID-JAG is a signed JWT with the header typ set to oauth-id-jag+jwt. That explicit type stops it being confused with an ID token or an access token.

{
  "header": {
    "typ": "oauth-id-jag+jwt",
    "alg": "RS256",
    "kid": "idp-signing-key-2026"
  },
  "payload": {
    "iss": "https://idp.customer.example",
    "sub": "00u8f2k1employee",
    "aud": "https://auth.your-saas.example",
    "client_id": "https://agent.vendor.example/oauth/client.json",
    "jti": "9f1c2e7a-3b4d-4c8e-a1f0-5d6e7f8a9b0c",
    "scope": "tickets.read",
    "iat": 1791206400,
    "exp": 1791206700
  }
}

Illustrative decoded ID-JAG. Values are invented; field set follows the draft's core claims. Note the five-minute lifetime.

Read it as a sentence. "The IdP at iss asserts that user sub, using client client_id, may get a token from authorization server aud with scope scope, once (jti), before exp."

Step 3: jwt-bearer grant at your authorization server

The requesting app sends the ID-JAG to your authorization server using the RFC 7523 JWT bearer grant.

POST /oauth/token HTTP/1.1
Host: auth.your-saas.example
Content-Type: application/x-www-form-urlencoded
 
grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer
&assertion=eyJ0eXAiOiJvYXV0aC1pZC1qYWcrand0IiwiYWxnIjoiUlMyNTYifQ...

Illustrative request. Client authentication to your AS is omitted for brevity.

Your authorization server must advertise that it accepts this grant. Put urn:ietf:params:oauth:grant-type:jwt-bearer in grant_types_supported in your RFC 8414 authorization server metadata. Clients look for it there.

Step 4: access token and the API call

Your authorization server validates the ID-JAG, maps the user to a local account in the right tenant, and issues its own short-lived access token. The requesting app calls your API or MCP server with that token. The IdP is not in the request path from here on.

No consent screen appeared at any point. The decision was made once, by the customer's admin, in the IdP.

What your SaaS (the resource app) must build

This is the side most B2B builders own. Most of the trust plumbing already exists in your enterprise SSO stack.

1. Trust the customer IdP per tenant. Reuse the SSO connection you already store on the Organization object. The issuer, JWKS location, and tenant mapping are the same facts your multi-tenant SSO setup holds. An ID-JAG from an IdP that is not configured for any tenant fails closed. Never accept an ID-JAG from an issuer just because it validates.

2. Validate every ID-JAG.

  • Header typ is oauth-id-jag+jwt. Reject anything else.
  • Signature verifies against the tenant IdP's published JWKS.
  • iss matches the IdP configured for exactly one tenant.
  • aud equals your authorization server's issuer identifier.
  • client_id is a CIMD URL (or pre-registered client) you recognize and allow for that tenant.
  • sub maps to a user already linked to that tenant through SSO. Do not JIT-create a user from an ID-JAG unless you have decided to, deliberately.
  • exp is short and in the future. iat is recent.
  • jti has not been seen before. Store it until exp passes to block replay.

3. Issue a short-lived, scoped-down access token. Grant the intersection of what the ID-JAG asked for and what your own policy allows for that user and client. Never widen scope beyond the assertion. Keep lifetimes short, because revocation at the IdP only stops new ID-JAGs. Token Management for AI Agents covers lifetime and sender-constraint choices.

4. Audit both identities. Every token issuance and every API call should log the agent client_id and the user sub, plus tenant, scopes, and the jti it came from. Without both, an incident review cannot separate "the user did this" from "an agent did this as the user."

5. Publish metadata. Advertise the jwt-bearer grant in grant_types_supported. If you run an MCP server, it must also publish RFC 9728 Protected Resource Metadata under the 2025-11-25 MCP spec.

What the requesting app must build

If you ship the agent or app that calls other SaaS apps, the work is on the other side.

  • Sign users in through the enterprise IdP with OIDC so you hold an ID token to exchange.
  • Publish a CIMD and use its URL as your client_id everywhere. The checklist below covers hosting.
  • Run the token exchange at the IdP for each target resource app, with the right audience and resource.
  • Run the jwt-bearer grant at each resource AS. Read its metadata first to confirm grant_types_supported includes jwt-bearer.
  • Handle refusal cleanly. An IdP refusal is a policy decision, not an error to retry. Surface it to the user.
  • Support the MCP extension explicitly if you are an MCP client. MCP extensions are optional and never on by default.
  • Never pass tokens through. The MCP spec forbids token passthrough. Each resource gets its own token.

CIMD hosting checklist

These rules come from draft-ietf-oauth-client-id-metadata-document-02 and the MCP 2025-11-25 authorization spec.

RuleWho it bindsWhy
client_id is an https URL with a path, no fragment, no userinfoClientThe URL is the identity. Ambiguous URLs are spoofable.
The document contains client_id equal to the URL exactlyClientProves the document describes itself, not another client.
Served with HTTP 200ClientAnything else is not a valid document.
No symmetric secrets. Public keys only (jwks or jwks_uri for private_key_jwt)ClientThe document is public.
Keep it under the recommended 5 KBClientAuthorization servers fetch it on the hot path.
Every redirect URI is listed in the documentClientThe AS rejects unlisted redirects.
Respect HTTP cache headers; never cache errorsAuthorization serverFreshness without hammering the client's host.
Never fetch URLs that resolve to special-use IPsAuthorization serverThe fetch is an SSRF vector.
Display the client_id hostname to usersAuthorization serverA pretty client_name is easy to phish with.
Warn on localhost-only redirect URIsAuthorization serverAnyone can claim a CIMD URL with a localhost redirect and impersonate a client.

The last row is the one teams miss. A desktop or CLI agent with a localhost redirect cannot prove it is the software named in the CIMD. In the enterprise-managed flow the IdP policy narrows that risk, but your authorization server should still treat such clients with care.

Where it fits against the alternatives

ApproachWho decides accessClient identityUser in the loopBest fit
Plain OAuth consentEach user, per grantPre-registered, CIMD, or DCRYes, at consentConsumer apps, SMB, no enterprise IdP
Pre-registrationYour team, per clientStatic client_id you issuedDepends on grantSmall set of known partners
Dynamic Client RegistrationThe client registers itselfGenerated client_idYes, at consentBackward compatibility in MCP
CIMDClient publishes; AS fetchesHTTPS URLYes, at consent (alone)Open ecosystems of unknown clients
RFC 8693 delegation (act claim)Your AS, per exchangeExisting tokensNoService-to-service chains inside one trust domain
Enterprise-Managed Authorization (ID-JAG)Customer admin, in the IdPCIMD URL inside the ID-JAGNo consent screenB2B SaaS with enterprise SSO customers

The MCP 2025-11-25 spec sets a client registration priority: pre-registered first, then CIMD when the AS metadata has client_id_metadata_document_supported: true, then DCR via registration_endpoint, then prompting the user. Enterprise-Managed Authorization sits on top of that. It changes who grants access, not how the client is named.

Vendor status as of 2026-10-05

This table reflects public announcements and docs only. Preview and early access features change. Verify every row in a proof of concept before you plan around it.

VendorStatusSideSource
OktaAgent SSO GA, 24 Aug 2026; reconfirmed at Oktane, 22 Sep 2026IdP (issues ID-JAGs)WorkOS analysis; Okta press release
Auth0Resource-app side Early Access. Requesting-app side moved to Early Access 31 Aug 2026, running on Token Vault over ID-JAG. Plans: Enterprise, B2B Pro, B2B EssentialBothWorkOS analysis; Auth0 docs and blog
DescopeAnnounced ID-JAG issuance and validation, 1 Sep 2026, in its Agentic Identity Hub. Tenant admins can self-configure XAABothDescope press release; WorkOS analysis
SSOJetShipped MCP Authentication, 30 Sep 2026: an open-source MCP server template on Cloudflare Workers, with users authenticating through SSOJet before reaching tools. No ID-JAG claimMCP server auth, not ID-JAGSSOJet announcement
WorkOSPublished the convergence analysis. Check current docs for product supportVerifyWorkOS blog
Scalekit and othersNo verified ID-JAG claim in our sourcesVerifyn/a

WorkOS noted that Okta, Auth0, and Descope moved within eight days of each other. That is fast convergence on a draft, which is a signal to prepare. It is not a signal that the draft is final.

Limitations and open questions

Both specs are drafts. ID-JAG is at -04 and CIMD at -02 as of this writing. Both are adopted by the OAuth WG, which means work continues and details can change. Pin the draft version you implement and track the datatracker pages.

The client has to support it. The MCP extension is optional and needs explicit client support. If the agent your customer uses does not implement the extension, the flow does not start.

The IdP has to support it. Your customer's IdP must issue ID-JAGs. If it does not, nothing you build on the resource side gets exercised. Ask your largest customers which IdP they run before you prioritize this.

Consumer CIAM is out of scope. The entire model rests on an enterprise IdP that you already trust for SSO and an admin who writes policy. A consumer app has neither. Consumer agent access still runs on OAuth consent. See Authentication for AI Agents for that side.

Revocation is split across two systems. Policy changes at the IdP stop new ID-JAGs. Access tokens your AS already issued live until they expire unless you revoke them. Short access token lifetimes are the practical answer today.

Scope translation is yours. The IdP decides at the app level. Mapping that decision onto your own scopes and object-level permissions is your job. Authorization Patterns for Agentic Workflows covers the per-action layer.

The deeper reason this matters is that agents do not carry passwords or sit through MFA prompts. The trust has to come from somewhere else, as argued in AI agents don't have passwords.

When to implement now and when to wait

If you buy rather than build, the decision is which CIAM provider already validates ID-JAGs on the resource side for your plan tier. Run that check in a POC against a real IdP tenant, not against the marketing page. For the broader agent identity stack this sits inside, see AI Agent Identity and MCP.

Related guides

Related vendors

Where to next

FAQ

What is Enterprise-Managed Authorization?
It is a pattern where an enterprise's identity provider decides whether a given app or AI agent may get an access token to another SaaS app for a given employee. The requesting app asks the IdP for an Identity Assertion JWT Authorization Grant (ID-JAG), then trades it at the SaaS app's authorization server for an access token. The name comes from the MCP extension io.modelcontextprotocol/enterprise-managed-authorization. Okta markets the same pattern as Cross App Access (XAA).
What is the difference between ID-JAG and Cross App Access?
ID-JAG is the token and the IETF protocol: draft-ietf-oauth-identity-assertion-authz-grant. Cross App Access is Okta's product name for deployments built on it. Enterprise-Managed Authorization is the MCP extension name for the same flow. One protocol, three labels.
What is a Client ID Metadata Document (CIMD) and why does it matter here?
A CIMD makes an OAuth client_id an HTTPS URL that serves a JSON document describing the client. The authorization server fetches it instead of requiring prior registration. In an ID-JAG, the client_id identifies the requesting app or agent. A CIMD URL gives every party a stable, verifiable name for that software without a registration call.
Does my SaaS app need to support ID-JAG to sell to enterprises using AI agents?
Not yet as a hard requirement, but the pressure is real. The flow only works when the customer's IdP issues ID-JAGs and the agent client supports the extension. If your enterprise customers run an IdP that ships it, supporting the resource side lets their admins govern agent access centrally instead of approving per-user OAuth grants.
Is this the same as RFC 8693 delegation with an act claim?
No. RFC 8693 token exchange is the transport for the first step, but ID-JAG is not a delegation chain token. It is an IdP-signed assertion that a specific user, via a specific client, may get a token from a specific resource authorization server. Your authorization server then issues its own access token.
Can I use Enterprise-Managed Authorization for consumer apps?
No. The model depends on an enterprise IdP that the resource app already trusts for SSO and an admin who writes policy. Consumer CIAM has neither. Consumer agent access still runs on standard OAuth consent, with CIMD or DCR for client registration.
How do I revoke an agent's access under this model?
Change the policy at the IdP so it stops minting ID-JAGs for that app, user, or resource. That blocks new tokens. Tokens your authorization server already issued remain valid until they expire unless you revoke them yourself, so keep access token lifetimes short.

Sources

Last reviewed 2026-10-05.