> ## Documentation Index
> Fetch the complete documentation index at: https://docs.runlayer.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Cross App Access (XAA) with Okta

> Let Runlayer reach XAA-capable MCP servers through Okta policy instead of per-user OAuth consent.

With Cross App Access (XAA), Runlayer gets the access token for an upstream MCP server from your Okta policy, not from a consent screen each user clicks through. Your Okta admin approves Runlayer's connection to each vendor once, the vendor trusts your Okta org, and users call tools with no consent prompts.

> [!NOTE]
>
> Cross App Access is in early access. Contact your Runlayer account team to enable it for your organization.

## Why XAA

Standard OAuth leaves the security decision to each user. XAA moves it to your admins.

* **No consent screen to phish.** With standard OAuth and open dynamic client registration, any client can register under any name, and the only control is the user's consent click. That is the pattern behind illicit consent grant attacks. With XAA there is no consent screen for an attacker to imitate.
* **Admin policy instead of user consent.** Your Okta admin decides which users and groups can use Runlayer with which vendor. The vendor admin decides to trust your Okta org.
* **The right account, every time.** With standard OAuth, the user picks which vendor account to connect, so a corporate Runlayer identity can end up paired with a personal or other-org account. With XAA, Okta asserts the user and the vendor maps that assertion to the org-managed account. Audit attribution stays consistent, data stays in your tenant, and offboarding a user in Okta cuts their access.
* **Verifiable identity.** The vendor identifies Runlayer by a client ID metadata document (CIMD) URL on your Runlayer domain, not by a self-reported name.
* **One kill switch and one audit trail.** Okta logs every assertion it issues. Removing the Runlayer connection to a vendor in Okta stops access for every user at once.

## How it works

XAA builds on the [Identity Assertion JWT Authorization Grant](https://datatracker.ietf.org/doc/draft-ietf-oauth-identity-assertion-authz-grant/) and the MCP Enterprise-Managed Authorization extension. Runlayer is the **requesting app**, and each upstream vendor is a **resource app**.

```mermaid theme={null}
sequenceDiagram
  autonumber
  participant U as User's AI client
  participant R as Runlayer
  participant O as Your Okta org
  participant A as Vendor authorization server
  participant M as Vendor MCP server
  U->>R: tools/call
  R->>R: Check identity, policies, and guardrails
  R->>O: Token exchange for this user and vendor
  O-->>R: Identity assertion (ID-JAG), if an admin connected Runlayer to this vendor
  R->>A: Redeem the assertion as Runlayer
  A-->>R: Short-lived access token
  R->>M: tools/call with the access token
  M-->>R: Result
  R-->>U: Governed, audited result
```

1. A user's AI client calls a tool on a Runlayer connector.
2. Runlayer applies its [policies](https://docs.runlayer.com/platform-policies.md) and guardrails as usual.
3. Runlayer asks Okta for an identity assertion (ID-JAG) for that user, addressed to the vendor. Okta issues one only if an admin connected Runlayer to that vendor and the user is allowed.
4. Runlayer redeems the assertion at the vendor's authorization server and receives a short-lived access token for that user. Runlayer caches the token until it expires.
5. Runlayer calls the vendor's MCP server and returns the result.

Approval lives in three places, and none of them is a per-user consent screen:

| Where | Who | What they approve |
| - | - | - |
| Okta | Okta admin | Which users and groups can use Runlayer, and which vendors Runlayer may request assertions for |
| Vendor | Vendor admin | Trusting your Okta org for enterprise-managed authentication |
| Runlayer | Runlayer admin | XAA as the connector's authentication method, plus policies, guardrails, and audit for every call |

## Supported features

* **Outbound XAA from Runlayer to upstream MCP servers.** Runlayer requests and redeems identity assertions for each user, with no consent prompts.
* **Okta as the identity provider.** Microsoft Entra ID does not issue identity assertions for XAA, so Entra organizations keep standard OAuth.
* **Upstream vendors.** Any MCP server whose authorization server supports the identity assertion grant. See [Supported vendors](#supported-vendors).
* **Audit.** Runlayer records each assertion request and token redemption in [Audit Logs](https://docs.runlayer.com/platform-audit-logs.md), and Okta records each assertion in its System Log.

### Limitations

* Okta enables Cross App Access through Okta Support. Ask Okta to enable it for your org if it isn't on.
* Okta limits how many identity assertions it issues per user, per resource app, per month. Runlayer caches the vendor's access tokens to stay well within that limit.
* An XAA connector never falls back to OAuth consent. If an exchange fails, the tool call fails with an error that names the cause. See [Troubleshooting](#troubleshooting).
* Vendors' enterprise-managed authentication features can be in beta and their scopes can change. Check the vendor's documentation.
* Each vendor decides which requesting apps it accepts. Some vendors' guides currently name only specific AI clients. Contact your Runlayer account team for the current status of a vendor.

## Supported vendors

These MCP servers support enterprise-managed authentication with Okta. Each vendor has its own plan requirement and admin setting; the setup steps for each are in [step 3](#configure-cross-app-access).

| Vendor | MCP server URL | Vendor requirement | Vendor guide |
| - | - | - | - |
| Asana | `https://mcp.asana.com/v2/mcp` | See Asana's guide | [Cross-app access](https://help.asana.com/s/article/cross-app-access) |
| Atlassian | `https://mcp.atlassian.com/v1/mcp/authv2` | Atlassian organization admin | [Configure enterprise-managed authentication](https://support.atlassian.com/security-and-access-policies/docs/configuring-enterprise-managed-authentication/) |
| Canva | `https://mcp.canva.com/mcp` | See Canva's guide | [Manage cross app access](https://www.canva.com/help/manage-cross-app-access/) |
| Datadog | `https://mcp.datadoghq.com/api/unstable/mcp-server/mcp` | SAML SSO to Datadog through Okta; `org_management` permission | [Cross-App Access](https://docs.datadoghq.com/account_management/org_settings/cross_app_access/) |
| Figma | `https://mcp.figma.com/mcp` | Organization or Enterprise plan, with SAML SSO through Okta | [Set up MCP enterprise-managed auth](https://help.figma.com/hc/articles/41992841175959) |
| Granola | `https://mcp.granola.ai/mcp` | Enterprise workspace with SSO | [Enterprise-managed authorization](https://docs.granola.ai/help-center/sharing/integrations/mcp#enterprise-managed-authorization) |
| Linear | `https://mcp.linear.app/mcp` | SAML SSO to Linear through Okta | [MCP: Enterprise-managed authorization](https://linear.app/docs/mcp#enterprise-managed-authorization) |
| Notion | `https://mcp.notion.com/mcp` | Enterprise plan, with SAML SSO through the same Okta org | [Set up enterprise-managed connections](https://www.notion.com/help/set-up-enterprise-managed-connections-for-notion-mcp) |
| Slack | `https://mcp.slack.com/mcp` | Enterprise+ plan; Slack Org Owner | [Manage access to the Slack MCP server](https://slack.com/help/articles/54548358406419) |
| Supabase | `https://mcp.supabase.com/mcp` | Team or Enterprise plan, with SSO | [Enterprise MCP authentication](https://supabase.com/docs/guides/platform/sso/enterprise-mcp-authentication) |

In every case, the vendor's app must already be in your Okta org with your users assigned.

## Prerequisites

* An Okta org with the Single Sign-On product and Cross App Access enabled.
* Your users sign in to Runlayer with Okta.
* Cross App Access enabled for your Runlayer organization (early access).
* Admin access in Okta, in Runlayer, and in each vendor you connect.
* A vendor plan that supports enterprise-managed authentication. See [Supported vendors](#supported-vendors).

## Configure Cross App Access

**1. Add Runlayer to Okta**

1. In the Okta Admin Console, go to **Applications → Applications → Browse App Catalog**, search for **Runlayer**, and click **Add Integration**.
2. Enter your Runlayer domain, for example `acme.runlayer.com`.
3. Make sure the app's sign-in redirect URIs include `https://<your-runlayer-domain>/api/v1/xaa/link/callback`. Runlayer uses it to connect each user's Okta account.
4. On the **Assignments** tab, assign the users and groups who should use Runlayer.

Users must be assigned to the Runlayer app before Okta issues identity assertions for them.

**2. Connect Runlayer to each vendor in Okta**

Each connection is a one-way approval: Runlayer may request assertions for this vendor.

1. Open the vendor's app in Okta (the app you use for single sign-on to that vendor). On its **Resource server** tab, turn on **Cross App Access (XAA)** and enter the issuer and audience values from the vendor's tab in step 3, where the vendor lists them.
2. Open the Runlayer integration, or its AI agent under **Directory → AI Agents** if your org uses AI agents, and add a **Resource connection**.
3. Select the vendor's application instance.
4. For the client ID registered at the vendor, enter Runlayer's client ID metadata document URL:

   ```
   https://<your-runlayer-domain>/.well-known/oauth-client/runlayer
   ```

   If the vendor issues its own client ID to Runlayer instead, enter that one. The vendor's tab in step 3 says which.
5. Choose the scopes to allow, and save. If the vendor's tab says to allow all scopes, do that; the vendor enforces scopes itself.

**3. Turn on enterprise-managed authentication at the vendor**

Each vendor's guide is linked in [Supported vendors](#supported-vendors). Do the vendor step before you test the connection in Runlayer.

> [tab] Asana
>
> Follow Asana's [cross-app access guide](https://help.asana.com/s/article/cross-app-access) to trust your Okta org, then return to step 4.

> [tab] Atlassian
>
> 1. In Atlassian Administration, select your organization, then go to **Connectors → Atlassian MCP server → Authentication**.
> 2. Turn on **Allow enterprise managed authentication**, select **Edit URL**, and enter your Okta org URL, for example `https://acme.okta.com/`.
> 3. In Okta, on the Atlassian app's **Resource server** tab:
>    * **Issuer URL:** the Atlassian authorization server, `https://auth.atlassian.com/<id>`, as listed in the Atlassian MCP server's metadata.
>    * **Audience:** your site's cloud ID, from `https://<your-site>.atlassian.net/_edge/tenant_info`.
>
> If you restrict XAA scopes in Okta, add the new scopes when Atlassian releases its next MCP server version, or existing connections stop working.

> [tab] Canva
>
> Follow Canva's [cross app access guide](https://www.canva.com/help/manage-cross-app-access/) to trust your Okta org, then return to step 4.

> [tab] Datadog
>
> 1. In Datadog, go to **Organization Settings → Cross-App Access** and click **Enable**.
> 2. In **Issuer URL**, enter your Okta org URL (a subdomain of `okta.com`, `oktapreview.com`, or `okta-emea.com`) and click **Save**.
> 3. Copy the **Org UUID**. In Okta, on the Datadog app's **Resource server** tab, enter it as the **Audience**.
> 4. In Okta, set the resource connection's scope condition to **Allow all**. Datadog enforces scopes itself, under **Organization Settings → Mobile and Third-Party Access**.
>
> Datadog's Cross-App Access is in preview and isn't available on its government sites.

> [tab] Figma
>
> 1. In Figma, open **Admin → Settings**.
> 2. In **Login and provisioning**, choose **Enterprise-managed authorization for MCP**.
> 3. Enter your Okta org URL and click **Save**.

> [tab] Granola
>
> 1. In Granola, go to **Settings → Workspace → General → Apps & connectors → MCP access**, and choose which notes MCP clients can access.
> 2. In Okta, on the Granola app's **Resource server** tab, turn on **Cross App Access (XAA)** with:
>    * **Resource URL:** `https://mcp.granola.ai/mcp`
>    * **Issuer URL** and **Audience:** `https://mcp-auth.granola.ai`
>    * **Scope:** `mcp`

> [tab] Linear
>
> 1. In Linear, open your Okta identity provider settings.
> 2. Turn on **MCP enterprise managed authentication**.
> 3. Paste your Okta org's issuer URI, for example `https://acme.okta.com`.

> [tab] Notion
>
> 1. In Notion, go to **Settings → Identity → Enterprise-managed connections**. If an organization manages SAML, use the organization console instead.
> 2. Turn on enterprise-managed connections, and confirm the Okta issuer URL. It must be the Okta org that runs your Notion SAML SSO.
> 3. Choose the workspace this connection manages, and select **Turn on**.
>
> Removing a user in Okta blocks new connections, but an active connection can last up to eight hours. To cut access immediately, also disconnect the member in Notion.

> [tab] Slack
>
> 1. As a Slack Org Owner, install the Runlayer app at the org level: **Tools & settings → Organization settings → Integrations → Manage Apps → Install an app**. Then use **Add to more workspaces** to add it to each workspace.
> 2. Go to **Organization settings → Security → SSO settings**. Next to **Enterprise-Managed Authorization**, click **Edit**, turn it on, verify the ID-JAG issuer URL, and click **Save**.

> [tab] Supabase
>
> 1. In your Supabase organization settings, open **SSO → Advanced settings**, enter your Okta org URL as the **IDJAG Issuer**, and save.
> 2. An organization owner or admin connects Runlayer to Supabase once through the standard sign-in flow and approves it. Runlayer then appears under **Authorized Apps**, where you can review or revoke it.

**4. Set the connector to Cross App Access in Runlayer**

1. In Runlayer, add the vendor's connector from the catalog or open an existing one, and go to its **Settings**. Use the MCP server URL from [Supported vendors](#supported-vendors).
2. Choose **Cross App Access (XAA)** as the authentication method. Runlayer pre-selects it when the upstream server supports XAA.
3. Leave the scopes blank. Runlayer discovers them from the vendor.
4. Click **Test connection**. Runlayer checks each stage: discovery, the Okta exchange, the vendor redemption, and listing tools.
5. Save the connector.

**5. Users connect their Okta account on first use**

The first time a user calls a tool on an XAA connector, Runlayer asks them to connect their Okta account, so it can request assertions for them. Clients that support link prompts (Claude Code, Codex, Cursor, VS Code) show a prompt that opens the link. Other clients return a tool error that contains the link. Until the user connects, the connector lists a single `AUTH_REQUIRED_<connector>` tool that returns the same link.

The link opens Runlayer, which sends the user through a normal Okta sign-in. If they're already signed in to Okta, it completes without a prompt. Okta returns them to Runlayer, which confirms whether the account is connected. Each user connects once, and that connection covers every XAA connector. There is no consent screen. The user may need to reconnect the MCP server in their client to see the connector's tools.

**6. Verify**

1. As an assigned user, call a tool on the connector from any AI client connected to Runlayer. Open the link Runlayer offers, and sign in to Okta if asked. No consent screen appears.
2. Call the tool again. It runs with no prompt.
3. In Runlayer **Audit Logs**, find the XAA token exchange for that user and connector.
4. In the Okta System Log, find the matching identity assertion issued to Runlayer.

## Lock down other paths

An XAA connection adds a governed path. It does not close the others: a user can still add the vendor's MCP server to their AI client directly and click through the vendor's consent screen. To make Runlayer the only path to a vendor, lock down each layer.

| Layer | Admin action | Closes |
| - | - | - |
| Okta | Connect Runlayer to the vendor. Don't connect AI clients (such as Claude) directly to the vendor | AI clients getting vendor tokens through Okta without Runlayer |
| Vendor | Restrict which apps and OAuth clients can connect, allow only Runlayer's client, and revoke existing grants to other AI clients | Users consenting to another AI client at the vendor |
| AI client | Use the client's connector allowlist, and deploy MCP configuration through your MDM that lists only Runlayer | Users adding the vendor's MCP URL directly |
| Runlayer AI Watch | Turn on [Enforce](https://docs.runlayer.com/shadow-ai/enforce.md) so direct MCP connections to sanctioned vendors are flagged or blocked | Direct connections from managed devices |

AI Watch can't see connectors that an AI client hosts in its own cloud. The AI client's connector allowlist covers those.

With these in place, removing Runlayer's connection to a vendor in Okta revokes every user's agent access to that vendor.

## Sign in to Runlayer

Runlayer supports sign-in that starts from Runlayer:

1. Go to your Runlayer domain, for example `https://acme.runlayer.com`.
2. Click **Sign in**. Runlayer redirects you to Okta.
3. Sign in to Okta. Okta returns you to Runlayer, signed in.

## Troubleshooting

| Symptom | Cause | Fix |
| - | - | - |
| Tool calls fail with `xaa_link_required` | The user hasn't connected their Okta account, or Okta revoked or expired the connection | Open the link in the error. Runlayer removes a revoked connection, so the next tool call offers the link again |
| Runlayer shows **Okta sign-in wasn't completed** | The user left Okta's sign-in page before finishing | Click **Try again**. Getting back from Okta's sign-in page can take two Back presses |
| Okta shows a redirect URI error when a user connects | The Runlayer app in Okta doesn't list the callback URI | Add `https://<your-runlayer-domain>/api/v1/xaa/link/callback` (step 1) |
| Okta rejects the exchange (`invalid_target`) | No resource connection from Runlayer to this vendor in Okta | Add the resource connection (step 2) |
| Okta rejects the exchange for one user | The user isn't assigned to the Runlayer app or the vendor app in Okta | Assign the user to both apps |
| The vendor rejects the assertion (`invalid_grant`) | Enterprise-managed authentication is off at the vendor, the vendor trusts a different Okta org, or the client ID in the Okta connection doesn't match Runlayer's | Recheck step 3, and confirm the client ID is your Runlayer domain's metadata document URL |
| Atlassian rejects the token for your site | The Okta Atlassian resource app's audience isn't your site's cloud ID | Set the audience to the cloud ID from `/_edge/tenant_info` |
| Okta rejects the exchange for Datadog | The resource connection lists specific scopes | Set the scope condition to **Allow all** |
| **Test connection** fails at discovery | The connector URL isn't the vendor's XAA-capable endpoint | Use the MCP server URL from [Supported vendors](#supported-vendors). For Atlassian, that's `https://mcp.atlassian.com/v1/mcp/authv2` |

For anything else, contact [support@runlayer.com](mailto:support@runlayer.com) with the connector name, the time of the failed call, and the error message.

## Learn more

* [Connectors](https://docs.runlayer.com/platform-connectors.md)
* [Connector OAuth clients](https://docs.runlayer.com/connector-oauth-clients.md)
* [Policies](https://docs.runlayer.com/platform-policies.md)
* [Audit Logs](https://docs.runlayer.com/platform-audit-logs.md)
* [Okta: Cross App Access](https://help.okta.com/oie/en-us/content/topics/apps/apps-cross-app-access.htm)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.