Classic painting used as the article cover
← Back to blog

ENTERPRISE

Cross-App Access: The Enterprise Problem Behind Agent SaaS Sprawl

An employee-authorized agent accumulates OAuth grants across a dozen SaaS tenants, each surviving offboarding alone. The federation standards that make that governable are arriving now.

Paulina XuSep 16, 202618 min
IdentityGovernanceProtocols

TL;DR

Agent SaaS sprawl isn't a discipline problem. It's an architecture problem, and the fix is moving the authorization decision to the identity provider a company already runs.

Eight hundred employees clicking "allow" on eight hundred separate OAuth consent screens produce thousands of refresh tokens that outlive employment, survive independently of each other, and answer to no single system. Okta's Cross-App Access ecosystem already lists more than two dozen partners spanning identity providers, agent vendors, and the SaaS applications they connect to.

Telling employees to be more careful doesn't touch this. The problem isn't carelessness. It's that no system holds the union of what's been granted, so there's nothing to be careful with.

We're not saying this is solved. Coverage is partial, the core specification is still a working-group draft, and an application that hasn't implemented it keeps handing out tokens exactly as it does today.

What's changed is that three IETF and OpenID specifications went from draft to genuinely usable in the last year. A company running its own IdP can start requiring brokered access from the vendors that support it, and push the rest.

Overview

Take an employee at a four-thousand-person company who installs an AI assistant and connects it to Slack, then Google Drive because meeting prep needs the documents, then Jira because the sprint board is context, then Salesforce, Confluence, Zoom, Figma, Datadog. Each connection is an ordinary OAuth authorization-code flow. Each is legitimate: a real user consenting to real scopes on their own data. Each also produces a refresh token held by a vendor the company has no contract with, and that token survives independently of every other grant the employee has made.

Multiply by eight hundred employees doing some version of the same thing. What comes out the other side is an access topology no one has ever seen in full: several thousand credentials the company did not issue, cannot enumerate, and cannot revoke centrally. When that employee leaves, IT disables their identity-provider account. The refresh token the assistant vendor is still holding for Salesforce doesn't notice.

Credential hygiene and agent offboarding get covered as practices elsewhere on this site. This post is about the layer underneath them: four federation standards, at wildly different stages of readiness, that change who is actually in the loop when an agent gets access to company SaaS in the first place.

The IETF's Identity Assertion JWT Authorization Grant (the industry mostly just calls it Cross-App Access) is a working-group document at revision 04. The OpenID Foundation's Shared Signals Framework and CAEP reached Final Specification status in September 2025. IPSIE is profiling the whole enterprise identity stack, agents included. And SCIM extensions for agents exist as two competing individual drafts, neither adopted by a working group yet. Getting precise about which of those four is real infrastructure and which is still a good idea on paper is most of what this post is for.

The governing insight: every individual OAuth grant is small and reasonable on its own. Sprawl is what piles up when nobody owns the aggregate. Move the decision to the one system that already has enterprise context, and there's finally something to own.

How Sprawl Accumulates

We want to state the mechanics precisely, because this isn't a carelessness problem and it can't be trained away.

In the app-to-app model, the assistant is an OAuth client to each SaaS tenant independently. The employee is redirected to Salesforce, authenticates (often through the company's own IdP, which is the cruel part: SSO is involved and still learns nothing about what's being authorized), consents to a scope set, and the assistant receives tokens. From the IdP's perspective, a user logged into Salesforce. That's all it saw.

Three properties follow, and each is bad on its own.

Invisibility. No system holds the union of these grants. Salesforce knows about its own; Slack knows about its own. Enumerating the set means an administrator visiting every SaaS admin console, finding the connected-apps page, and reading it, assuming that page exists, exposes third-party grants, and is exportable. Plenty don't.

Independent survival. Each grant's lifecycle is anchored to the SaaS tenant rather than to employment. Disabling the IdP account stops new interactive logins. It doesn't touch a refresh token already sitting in a vendor's database, because the refresh grant never consults the IdP in the first place.

Consent granularity mismatch, and drift. The consent screen offers whatever scopes the vendor defined, and the employee accepts them to make the tool work. Whether a marketing coordinator should be able to grant an external agent write access to the CRM is a company policy question, and it gets answered, implicitly and permanently, by the marketing coordinator. And when the vendor adds a feature and requests more scopes at the next connection, exposure grows on the vendor's release schedule, not the company's.

We don't count the usual responses to this as controls. An annual review of eight hundred SaaS admin consoles doesn't touch something that changes weekly. A consent screen an employee clicks through to get a tool working is a liability release, not governance.

Consider a meeting-prep agent that reads calendars, pulls the relevant documents, checks recent Slack threads with attendees, and summarizes open Jira tickets. That's four grants for one useful feature, held by one vendor, on behalf of one employee. It's a good product. It's also, at scale, several thousand credentials a security team cannot see.

IdP-brokered access

SSO once

grant per app,
per policy

Employee

IdP: policy + audit

Slack AS

Drive AS

Jira AS

CRM AS

Sprawl: app-to-app grants

consent

consent

consent

consent

sees logins only

Employee

Slack grant

Drive grant

Jira grant

CRM grant

Agent vendor holds
N refresh tokens

IdP

Slack | Drive | Jira | CRM each grant --> agent vendor holds N independent refresh tokens IdP .... sees logins only, no grant visibility, no revocation reach

IDP-BROKERED Employee --SSO once--> IdP [policy + audit + one revocation point] IdP --brokered grant per app, per policy--> Slack AS | Drive AS Jira AS | CRM AS -->

Figure 1 — The same access, granted two ways. The difference is whether the IdP is a bystander or the broker.

What IdP-Brokered Access Actually Means

The naive version of "route it through the IdP" would have the IdP issue access tokens for every SaaS API directly. That fails for an instructive reason: it would require every vendor to accept a foreign issuer's tokens for its own resources, abandoning control over its authorization decisions, scope definitions, rate limits, and token formats. No serious vendor will do that, and they shouldn't.

The design that works splits the decision. The IdP decides whether this client may act for this user against this application at all, a question it's positioned to answer because it already knows the employee, the group memberships, the device posture, and the policy in force. The resource application's authorization server decides what access to actually grant and issues its own token, because it owns the scopes and the data.

The Identity Assertion JWT Authorization Grant draft states this explicitly. Unlike profiles in which the IdP issues access tokens consumed directly by the resource server, it "preserves the Resource Authorization Server as the issuer of access tokens for its protected resources. This lets the IdP centralize federated identity, SSO trust, and the decision to broker cross-app access, while the Resource Authorization Server keeps independent control over its own access tokens."

The precondition is a trust triangle that mostly already exists. The client must have a relying-party relationship with the IdP for SSO, and the resource authorization server must independently trust that same IdP for SSO and subject resolution. Both are true in any company where the wiki and the chat app sit behind the corporate IdP, which is to say most companies. Cross-App Access extends that existing trust from authentication to API authorization, rather than asking anyone to establish something new. One consequence is where the user-experience win comes from: the resource authorization server doesn't need to obtain user consent again at the exchange step, because the IdP's administrative policy stands in for the per-app consent click. That's the whole point, and it's also why we'd want that policy to be right before anyone flips it on.

Cross-App Access on the Wire

The specification is draft-ietf-oauth-identity-assertion-authz-grant, at revision 04, published 21 May 2026, authored by Aaron Parecki of Okta, Karl McGuinness, and Brian Campbell of Ping Identity. It's a work item of the IETF's Web Authorization Protocol working group, with an intended status of Proposed Standard. It profiles the more general draft-ietf-oauth-identity-chaining ("OAuth Identity and Authorization Chaining Across Domains," revision 17 as of 19 July 2026), which leaves most of cross-domain token chaining unspecified. Cross-App Access is the part that gets pinned down enough to actually interoperate.

There are three steps. Step one is ordinary SSO. The employee signs in to the client through the corporate IdP, and the client receives an identity assertion (an OpenID Connect ID token or a SAML 2.0 assertion) plus, optionally, a refresh token.

Step two is a token exchange at the IdP, which returns not an access token but an intermediate artifact: the Identity Assertion JWT Authorization Grant, or ID-JAG.

http
POST /oauth2/token HTTP/1.1
Host: acme.idp.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://acme.chat.example/
&resource=https://api.chat.example/
&scope=chat.read+chat.history
&subject_token=eyJraWQiOiJzMTZ0cVNtODhwREo4VGZCXzdrSEtQ...
&subject_token_type=urn:ietf:params:oauth:token-type:id_token
&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
&client_assertion=eyJhbGciOiJSUzI1NiIsImtpZCI6IjIyIn0...

audience is REQUIRED and identifies the resource authorization server. Implementations MUST accept identity assertions as the subject_token; they MAY additionally accept a previously issued refresh token, letting a client obtain a fresh ID-JAG without dragging the user through SSO again. This is the request the IdP evaluates against administrator-defined policy, which is the moment enterprise governance actually happens.

The ID-JAG that comes back is a JWT with typ of oauth-id-jag+jwt, carrying iss, sub, aud, client_id, jti, exp and iat as required claims, plus optional resource, scope, authorization_details for Rich Authorization Requests, tenant, auth_time, acr, amr and act. Its lifetime is short (the MCP profile's example uses 300 seconds) because it carries a policy decision, not a credential meant for ongoing work.

json
{
  "typ": "oauth-id-jag+jwt",
  "alg": "RS256"
}
{
  "jti": "9e43f81b64a33f20116179",
  "iss": "https://acme.idp.example",
  "sub": "U019488227",
  "email": "user@example.com",
  "aud": "https://auth.chat.example/",
  "resource": "https://mcp.chat.example/",
  "client_id": "f53f191f9311af35",
  "exp": 1311281970,
  "iat": 1311280970,
  "scope": "chat.read chat.history"
}

Step three redeems the ID-JAG at the resource authorization server as an RFC 7523 JWT bearer assertion:

http
POST /oauth2/token HTTP/1.1
Host: auth.chat.example
Content-Type: application/x-www-form-urlencoded

grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer
&assertion=eyJhbGciOiJIUzI1NiIsI...
&client_id=https://client.example.com/client.json

The resource authorization server validates the typ, the audience and the signature against the IdP it trusts, resolves the subject to a local account (with just-in-time provisioning if policy allows), applies its own policy, and issues its own access token. Clients discover support by looking for urn:ietf:params:oauth:grant-profile:id-jag in the authorization_grant_profiles_supported field of the resource authorization server's metadata.

MCP has adopted this directly. The Enterprise-Managed Authorization extension in the modelcontextprotocol/ext-auth repository is marked Stable, and is explicitly "an application of the Identity Assertion JWT Authorization Grant for use within enterprise deployments of the Model Context Protocol." In that profile the MCP client is the client, the MCP server is the resource server, and the resource authorization server is whatever the MCP server advertises in its RFC 9728 protected resource metadata. The extension adds one requirement worth flagging: the issued access token MUST be audience-restricted to the MCP server identified by the resource claim in the ID-JAG.

SaaS APIResource ASEnterprise IdPAgent ClientUserSaaS APIResource ASEnterprise IdPAgent ClientUserSSO (MFA, device policy)ID Tokentoken-exchange, requested_token_type=id-jagaudience=Resource AS, scope=...evaluate admin policy:may this client act for this user here?ID-JAG (short-lived, signed)jwt-bearer grant, assertion=ID-JAGvalidate iss/aud/typ, resolve subject,apply local policyaccess token (aud = this API only)API calldata

Enterprise IdP ==ID Token==> Agent Client Client --token-exchange (requested_token_type=id-jag, audience=Resource AS)--> IdP IdP evaluates admin policy ==ID-JAG (short-lived, signed)==> Client Client --jwt-bearer grant, assertion=ID-JAG--> Resource AS Resource AS validates + resolves subject + local policy ==access token, aud = this API only==> Client Client --API call--> SaaS API -->

Figure 2 — Cross-App Access. The IdP decides whether; the resource authorization server decides what.

IPSIE: Profiling What Already Exists

Cross-App Access solves one problem. Enterprise identity has six or seven, the specifications for each already exist, and none of them agree on how they fit together. That's the gap IPSIE addresses.

The OpenID Foundation chartered the IPSIE working group in October 2024. The working group's name is Interoperability Profiling for Secure Identity in the Enterprise; its deliverable is the Interoperability Profile for Secure Identity in the Enterprise. Its method isn't to invent protocols but to profile existing ones (the working group names OpenID Connect, Shared Signals, OAuth 2.0, SCIM, "and more") into a single document with sections per use case.

The problem space IPSIE opens with is the useful part to read, because it fairly enumerates what enterprises can't currently do interoperably: single sign-on, lifecycle management, entitlements, risk signal sharing, logout, and token revocation. Every one of those has a specification. Almost none has a profile precise enough that two vendors implementing independently will interoperate on the first try, which is why enterprise identity integration is still measured in weeks per application. An agent getting access through an IdP inherits whatever the IdP can express and propagate, so IPSIE's relevance here is direct: it's the work of making that interoperable.

We'd rather state IPSIE's maturity plainly than dress it up. The specifications page lists a v1 draft, and records "None yet" for both Final Specifications and Implementer's Drafts. This is profile-stage work. Directionally right, and not something to write into a procurement contract this quarter.

Shared Signals and CAEP: Making Revocation Travel

The most valuable operational property of brokered access is that revocation finally has somewhere to originate. But origination isn't propagation, and unusually for this space, the standards for propagation are actually finished.

On 2 September 2025 the OpenID Foundation membership approved three Shared Signals specifications as Final: the OpenID Shared Signals Framework 1.0, OpenID CAEP 1.0, and OpenID RISC 1.0. A Final Specification carries intellectual-property protections for implementers and isn't subject to further revision, which is a materially different procurement posture than a draft.

The Shared Signals Framework is the transport: transmitters and receivers exchanging Security Event Tokens over a defined stream-management API. CAEP, the Continuous Access Evaluation Profile published 29 August 2025 by Tim Cappalli of Okta and Atul Tulshibagwale of SGNL, defines what the events mean. Its framing anticipates the agent case in passing: transmitters send continuous updates receivers use to "attenuate access to shared human or robotic users, devices, sessions and applications."

CAEP defines eight event types, all under https://schemas.openid.net/secevent/caep/event-type/:

Event typeSignals
session-revokedA session has been revoked; receivers should terminate applicable sessions
session-established / session-presentedA session was created, or an active one was observed at the transmitter
token-claims-changeClaims within a token have changed
credential-changeA credential was created, updated, revoked, or deleted
assurance-level-changeAuthentication strength changed, against a named framework
device-compliance-changeA device moved between compliant and non-compliant
risk-level-changeThe assessed risk level for a subject changed

A session-revoked event is an ordinary Security Event Token:

json
{
  "iss": "https://idp.example.com/123456789/",
  "jti": "24c63fb56e5a2d77a6b512616ca9fa24",
  "iat": 1615305159,
  "aud": "https://sp.example.com/caep",
  "txn": "8675309",
  "sub_id": {
    "format": "opaque",
    "id": "dMTlD|1600802906337.16|16008.16"
  },
  "events": {
    "https://schemas.openid.net/secevent/caep/event-type/session-revoked": {
      "event_timestamp": 1615304991
    }
  }
}

Put this together with brokered access and offboarding stops being an archaeology exercise. The employee is disabled at the IdP, which transmits session-revoked (and, where appropriate, credential-change) to every subscribed receiver. Receivers terminate sessions and invalidate the access tokens they issued off the back of an ID-JAG. No new ID-JAG can be minted for a disabled subject, so nothing renews. The chain closes from both ends: nothing new gets granted, and what already exists gets torn down.

SET: session-revoked

SET: session-revoked

SET: session-revoked

SET: session-revoked

refuse new ID-JAG

HR: termination

IdP: disable subject

Chat app

Wiki

CRM

MCP server

No renewal path

Kill sessions,
invalidate tokens

Figure 3 — A Shared Signals revocation event propagating. Brokering closes the front door; CAEP closes the back one.

SCIM and Agent Lifecycle

Everything above governs an agent acting for a user. It says nothing about the agent as a thing that exists, has an owner, and should eventually be decommissioned. That's a provisioning problem, and provisioning has a standard: SCIM, defined by RFC 7643 for the core schema and RFC 7644 for the protocol.

SCIM's object model has User and Group, and neither fits an agent well. An agent is not a person and not a group, and modelling it as a service account throws away exactly the attributes that matter: who owns it, what protocols it speaks, which application hosts it, whether it has a parent agent.

Two individual IETF submissions are attempting this, and their state is the honest headline. "SCIM Agents and Agentic Applications Extension" (draft-abbey-scim-agent-extension-00, 16 October 2025, by M. Abbey and R. S. Cohen of Okta) defines two resource types, Agent and AgenticApplication. The agent carries active as administrative status, agentType for classification, x509Certificates and subject for token federation, entitlements, roles and groups for access, owners referencing Users or Groups as accountable parties, parent for hierarchy, and a protocols attribute describing the interfaces it speaks, with types including A2A, OpenAPI and MCP-Server. That draft expired on 19 April 2026 and hasn't been revised.

"AI Agent Resource Extension for SCIM" (draft-wzdk-scim-agent-resource-00, 5 June 2026) takes a second run at the same ground, and its author list is the interesting part: Mark Wahl and Pamela Dingle of Microsoft, Danny Zollner of Okta, and Ismael Kazzouzi of Nextident. A cross-vendor draft from two of the largest enterprise identity vendors is a meaningful signal about where this lands. It's also still a revision-00 individual submission that no working group has adopted.

We think the reason to care despite that immaturity is that owners is the field the entire governance story depends on. An agent whose record names an accountable human appears in that human's access review, gets flagged when they leave, and has someone to ask about. An agent with no owner is a permanent orphan, and the industry already has enough of those.

What Changes Operationally

Set the specifications aside and consider what a security team can actually do differently.

  • One revocation point that reaches. Today, cutting off an agent means visiting every SaaS admin console. Under brokered access, refusing to mint an ID-JAG stops all future access to every participating application immediately, and CAEP tears down what's already been issued. That's the difference between a policy you can state and a control you can actually exercise.
  • Offboarding that completes. Disabling the IdP account becomes causally connected to agent access instead of merely adjacent to it. The token an agent holds can't outlive the employment, because it can't be renewed and is short-lived by construction.
  • Session events propagate instead of expiring. A device falling out of compliance, an assurance-level downgrade, a risk-score change: each becomes an input to whether an agent keeps working, instead of a fact discovered at the next login, hours later.
  • Scope policy set once, centrally. The MCP extension's own example: engineering-group members get read-only access from an AI code editor to the source-control server, while marketing-group members get read and write on internal documentation. That's a sentence an administrator writes once, not a decision eight hundred employees make individually on consent screens.
  • An inventory that exists. The IdP's exchange log is the enumeration nobody had: every brokered grant produces a record naming the client, the user, the target application, and the scopes. That's not the same as the export button on each vendor's admin console, when that button exists at all.

We'd treat one honest limitation as a design boundary rather than a gap to apologize for, because the MCP extension states it plainly: the visibility the IdP gains "is limited to the process of issuing the access token, but does not extend to the actual MCP traffic between the MCP Client and Server." Brokering governs access, not behaviour. What the agent does with a token it was correctly issued (which tools it calls, what it reads, whether it followed an instruction hidden in a document) is a runtime observability problem federation doesn't touch, and doesn't claim to.

Brokered access changes the question from "which of our thousands of grants exist?" to "what does our policy say?" That's a far better question, and it's the only one an organization can realistically answer at scale. It's also not the whole problem.

Where This Actually Stands

The maturity across this stack varies by more than an order of magnitude, and conflating the pieces is how architecture decisions go wrong.

ComponentStatus as of July 2026
Shared Signals Framework 1.0, CAEP 1.0, RISC 1.0Final Specifications, approved 2 September 2025
Identity Assertion JWT Authorization Grant (XAA)IETF OAuth WG draft, revision 04, May 2026
Identity Chaining Across DomainsIETF OAuth WG draft, revision 17, July 2026
MCP Enterprise-Managed Authorization extensionStable extension in modelcontextprotocol/ext-auth
IPSIEv1 draft; no Implementer's Drafts, no Final Specifications
SCIM agent schemaTwo individual drafts at revision 00; one expired

Deployment is genuinely beginning rather than hypothetical. Okta announced on 23 June 2026 that it was expanding its Cross App Access ecosystem, with availability for Okta Workforce customers through the Okta Integration Network in August 2026 and early access for Auth0 B2B SaaS customers at the end of July 2026. The named early-adopter list of twenty-five-plus organizations spans requesting applications such as Anthropic, Cursor, Docker and VS Code; resource applications such as Atlassian, Datadog, Figma, Linear, Slack and Supabase; and identity infrastructure including Cloudflare, Keycloak, Stytch and WorkOS. Okta describes XAA as formally incorporated as an official MCP authorization extension and as an open, vendor-neutral protocol, and reports MCP SDK support in TypeScript and Java with Python in progress.

We read that as encouraging, and only partly. A twenty-five-vendor ecosystem is real, and it is not the SaaS estate of an actual enterprise, which runs to hundreds of applications. Cross-App Access requires the resource application's authorization server to implement the profile; an application that hasn't will keep working exactly as it does today, handing out an app-to-app grant the IdP cannot see. Coverage will be partial for years, so the operational reality is a hybrid: a governed path for participating applications, and the old sprawl for the rest, with security value proportional to how much of the estate has actually moved.

Two more caveats. The core specification is a working-group draft that expires 22 November 2026 and may change before it becomes an RFC, so building against revision 04 means accepting some churn. And Cross-App Access deliberately doesn't solve the agent-as-actor problem. The draft permits an actor_token on the exchange and an optional act claim in the ID-JAG, but explicitly declines to define normative processing for either. The delegation semantics that would let a resource server distinguish an agent from the employee it works for are, in this profile, future work.

Conclusion

Agent SaaS sprawl is a federation problem wearing a credential-management costume. Every individual grant is defensible. The aggregate is ungovernable, because nothing in the app-to-app model gives any single system a view of the whole, or a lever over it. Telling employees to be more careful doesn't touch a structural property.

We think the fix is moving the decision to the identity provider that already holds the trust relationships, group memberships, and employment lifecycle, while leaving each application in control of its own access tokens. That's what Cross-App Access does, via a token exchange producing a short-lived, signed, audience-bound grant the resource authorization server redeems on its own terms. Shared Signals and CAEP make revocation travel afterward, and they're finished specifications rather than aspirations. IPSIE is the work of making the whole enterprise surface interoperable, and it's early. SCIM agent schemas are earlier still, and the owners attribute they're converging on is the one field that makes agent accountability possible at all.

The test for any agent access architecture is a single question: when an employee leaves on a Friday, what has to happen for every agent acting on their behalf to stop working? If the answer involves a spreadsheet of SaaS admin consoles, the architecture is app-to-app. If the answer is "the IdP stops issuing grants and emits a revocation event," it's brokered. That's the only version that survives actual contact with an enterprise.

Sources