Enable Your SAML Requesting App for Cross App Access

If you currently federate enterprise customers using Security Assertion Markup Language (SAML) and want to connect with third-party applications without migrating to OpenID Connect (OIDC), this Cross App Access (XAA) guide is for you.
The Identity Assertion Authorization Grant specification, the basis of XAA, was originally designed with OIDC in mind. To use it in SAML applications, you must accommodate specific security and uniqueness requirements. This guide details what you need to support and how to make resource requests to a third-party app using XAA.
Table of Contents
- How XAA in SAML works
- XAA implementation checklist for SAML-federated applications
- Making cross-application requests from your SAML app securely
- Configure your XAA SAML Requesting App in Okta
- Learn more about Cross App Access, SAML, and OAuth 2.0
How XAA in SAML works
When an agent (like one running in Claude) needs API access, it presents an Identity Assertion Authorization Grant (ID-JAG). The ID-JAG is a short-lived JSON Web Token (JWT) issued by the Identity Provider (IdP) for your app’s user. You exchange the ID-JAG token for an access token to the resource application you’re connecting with.
The sequence diagram shown below describes the SAML XAA flow and how your application fits in. You’ll handle the flow in two parts: where your application requests the ID-JAG from the IdP using a refresh token, and where your app requests the access token from the ID-JAG from the third-party resource app’s authorization server.
XAA implementation checklist for SAML-federated applications
Follow the guide in this section to support XAA in your SAML application when your app connects to a third-party resource application. The XAA flow places the burden of token validation onto the IdP and the resource app’s authorization server. The initial SSO step remains the same; however, you’ll add three requests before getting an access token to make the resource API call.
Once the user completes signing in, you’ll:
- Request an OAuth refresh token from Okta
- Request the ID-JAG token from Okta
- Request the OAuth access token from the third-party resource app’s OAuth authorization server
Request the refresh token
Your SAML application makes the initial SSO handshake and handles the SAMLResponse as usual. The ACS handler verifies the incoming payload and its digital signature, then extracts the underlying XML assertion. This assertion serves as the required credential for the subsequent exchange.
Immediately after validating the SAML response, in the same ACS request before redirecting the user onward, you’ll perform the first exchange. Base64-encode the assertion you extracted, then exchange it for a refresh token using Okta’s token endpoint. This exchange follows the OAuth 2.0 Token Exchange (RFC 8693) mechanism.
The refresh token HTTP request looks like this:
POST /oauth2/v1/token HTTP/1.1
Host: your-okta-domain.okta.com
Content-Type: application/x-www-form-urlencoded
grant_type=urn:ietf:params:oauth:grant-type:token-exchange&
subject_token=<base64url-encoded SAML assertion XML>&
subject_token_type=urn:ietf:params:oauth:token-type:saml2&
requested_token_type=urn:ietf:params:oauth:token-type:refresh_token&
scope=openid+offline_access&
client_id=<your_client_id>&
client_secret=<your_client_secret>
The IdP (Okta) responds with the refresh token. The refresh token is opaque and long-lived. Persist the refresh token for the session; never persist or use the SAML assertion past this exchange.
Request the refresh token
With the refresh token in hand, you have the credentials to request the ID-JAG token when your application needs resources from a third-party app. This exchange uses the same OAuth token exchange mechanism as the first step. You make the POST request to the same endpoint, Okta IdP, use the refresh token as your credential, and request the ID-JAG token type.
The HTTP request looks like this:
POST /oauth2/v1/token HTTP/1.1
Host: your-okta-domain.okta.com
Content-Type: application/x-www-form-urlencoded
grant_type=urn:ietf:params:oauth:grant-type:token-exchange&
subject_token=<the refresh_token from prior step>&
subject_token_type=urn:ietf:params:oauth:token-type:refresh_token&
requested_token_type=urn:ietf:params:oauth:token-type:id-jag&
audience=<the resource app's authorization server issuer URI>&
resource=<the resource app's API base URL>&
scope=<the resource app's required scopes>&
client_id=<your_client_id>&
client_secret=<your_client_secret>
The IdP responds with a short-lived, signed JSON Web Token (JWT), the ID-JAG, as the value in the access_token property within the payload.
Request the access token
Redeem the ID-JAG at the resource app’s authorization server’s token endpoint. The resource app’s authorization server handles the redemption request, not the IdP. This request uses the JWT Profile for OAuth 2.0 Client Authentication and Authorization Grants (RFC 7523). The ID-JAG is the assertion now, and you include the scopes required for the resource request. The scope matches the scopes requested in the ID-JAG request. The HTTP request looks something like:
POST /token HTTP/1.1
Host: the-resource-server.example.com
Content-Type: application/x-www-form-urlencoded
Authorization: Basic <base64(resource_as_client_id:resource_as_client_secret)>
grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&
assertion=<ID-JAG token>&
scope=todos.read
In the example HTTP request, the Authorization header uses the Basic scheme as a demo. Use the authorization scheme required by the resource application.
The response payload contains the access_token property, whose value is the access token. Use the access token to make the API resource request by using the value in the Authorization header. For example:
Authorization: Bearer <access_token>
Handle token expiration
ID-JAG tokens have a short timeline by design. When it expires, request a shiny new ID-JAG from the refresh token. Refresh tokens also have a lifespan. If the IdP rejects the refresh token due to expiration (you’ll see an invalid_grant error), then you need to obtain a new refresh token by having the user sign in via SSO again.
Making cross-application requests from your SAML app securely
With these steps complete, your SAML application is configured for Cross App Access. Agents can now authorize requests against your API while maintaining your existing production federation, eliminating the need for protocol migration.
You can now use Okta to make cross-application requests with your SAML app.
Configure your XAA SAML Requesting App in Okta
Let’s configure your SAML requester application in Okta. Before you begin, you’ll need:
- Values from your app (we’ll walk through the values needed below)
- An Okta Integrator Free Plan account. Sign up for a new account to test out the XAA feature
- xaa.dev for testing your requesting app
Cross App Access is an early access feature in Okta. New Integrator Free Plan account types include XAA support. If you have a paid Okta org plan and the following options are missing, contact your representative.
Sign in to your Integrator Free Plan org and open the Admin Console.
Enable AI Agent Identity Assertion:
- Navigate to Settings > Features > Early Access
- Find AI Agent Identity Assertion and Agent to Agent Connections, and enable both
You’ll need an Okta application representing your requesting app.
Navigate to Applications > Applications
In the Create a new app integration model, select SAML 2.0 and press Next.
In General Settings:
- App name: Enter a descriptive name for the app, for example, “Requesting App”.
- Press Next to continue
In Configure SAML:
- Single sign-on URL: Use the ACS URL of your requestor app, e.g., “https://requester-app-uri/saml/acs”
- Audience URI (SP Entity ID): Use the SP Entity of your requestor, e.g., “https://requester-app-uri/saml/metadata”
- Name ID format: select EmailAddress
- Application username: select Email
- Update application username on: select Create and update
- Press Next to continue
Press Finish to create the Okta SAML 2.0 application.
After creating the app, you’ll see more configuration options for your Okta SAML 2.0 requesting app. You’ll make changes in more than one tab.
Sign On configuration
Select the Sign On tab. To the right, locate the View SAML setup instructions under the header SAML Setup, open the saml-doc file, and copy the Identity Provider Single Sign-On URL and Identity Provider Issuer. You will need these values in your requesting app setup. On the same page, make sure you download the X.509 certificate and add it back to your requester app as idp-cert.pem.
Assignments configuration
Navigate to the Assignments tab and make the following configuration changes:
- Select Assign > Assign to People
- Search for your test user and select Assign
- Press Save and Go Back, then select Done
Now that we have the requesting app registered, it’s time to register a resource app on the Okta platform. You’ll also need an Okta application representing the resource app.
Navigate to Applications > Applications
In the Create a new app integration model, select SAML 2.0 and press Next.
In General Settings:
- App name: Enter a descriptive name for the app, for example, “Resource App for Testing”.
- Press Next to continue
In Configure SAML:
- Add https://idp.xaa.dev/saml-resource/acs for Single sign-on URL
- Add https://idp.xaa.dev/saml-resource/metadata for Audience URI (SP Entity ID)
- Name ID format: select EmailAddress
- Application username: select Email
- Update application username on: select Create and update
- Press Next to continue
⚠️ Note Please note that we’re providing these for setup; they don’t constitute a working SSO connection to the resource app. Also, don’t assume the
NameIDis an email address; it is whatever the customer’s SSO emits. Your matching set must remain consistent across your deployment.
Press Finish to create the Okta SAML 2.0 application.
After creating the app, you’ll see more configuration options for your Okta SAML 2.0 app. You’ll make changes in the resource server tab.
Resource Server extra configuration
Navigate to the Resource Server tab and make the following configuration changes:
- Select Enable XAA
- Issuer URL: Add this value to your Issuer URL: https://auth.resource.xaa.dev
Assignments configuration
Navigate to the Assignments tab and make the following configuration changes:
- Select Assign > Assign to People
- Search for your test user and select Assign
- Press Save and Go Back, then select Done
The next step is to set up xaa.dev for the resource app.
Go to Test your requesting app
Add your IdP issuer URL as your Okta Integrator account ID (i.e., https://your-okta-domain.okta.com)
Put your email into the Test user identifier example, name1234…@okta.com
Finally, select My ID-JAG is SAML-derived and add your SAML IdP entityID from the requesting app you created under the Sign On tab > SAML Setup > View SAML setup instructions, open the saml-doc file, and find the Identity Provider Issuer value (i.e., http://www.okta.com/
Register and configure the AI Agent in Okta
With your Okta SAML 2.0 requesting app and the resource app configured, register a new AI Agent in Okta. The AI Agent configuration defines the relationship between the Okta SAML 2.0-requesting app you have and the resource application, which in this case is xaa.dev. You’ll configure credentials, add your requesting app as a delegated caller, and connect the resource app as a Resource Connection.
In the Okta Admin Console:
- Navigate to Directory > AI Agents
- Select Register AI Agent > Register Manually
- Enter a Name, e.g., “Agent”
- Select Register
Select the AI Agent you just created to open its configuration. Configure the agent across the following tabs:
- On the Owners tab
- Select Assign individual owners
- Search for and add yourself as an owner
- Press Save
- On the Credentials tab (select the agent you’ve just created to see this tab)
- Copy the AI agent ID and add the value as the Client ID for your requesting app.
- Back in Okta, select the Add Public Key, and then press Generate new key. Okta generates a key pair and displays the private key. Under PEM, press Copy to clipboard, then store the key securely on your end. You’ll paste this private key into the Private key (PKCS8 PEM or private JWK) field in your requesting app, then save.
-
Also copy the kid and add it back to your requesting app
- On the Delegations tab
- Select Add Caller
- Search for the newly created Okta SAML requesting app
- Select Add Caller to confirm
- On the Resource Connections tab
- Select Add Resource Connection. Under the Resource section, select Application as the resource type.
- Under the Application section, choose your App configured for AI Agent access instance as the Resource app. (In this case, it should be the “Resources App”) from the dropdown menu and paste the Client ID from xaa.dev. (It should look something similar to
byora...)
- Under the Application section, choose your App configured for AI Agent access instance as the Resource app. (In this case, it should be the “Resources App”) from the dropdown menu and paste the Client ID from xaa.dev. (It should look something similar to
- Under Scope Condition, select Allow all
- Select Add to confirm
- Select Add Resource Connection. Under the Resource section, select Application as the resource type.
The final step is to activate the AI agent. Go to Actions and select Activate
Once the AI Agent is active, the configuration is complete. All checkmarks on the agent configuration page must be green.
Test the SAML 2.0 app
At this stage, you are all set to run the requesting app and verify the complete XAA flow it is supposed to perform.
Validate the XAA connection end-to-end
Once the flow is complete in the SAML 2.0 application, return to xaa.dev. In the Live verification tab, a green Conformance passed panel appears. This confirms all steps:
- Auth Server Accepted your ID-JAG
- Access token was issued
- Resource Server accepted your access token
- API call to the /api/todos/ was a success.
At this stage, the JSON conformance log will have the complete details of the XAA flow.
Learn more about Cross App Access, SAML, and OAuth 2.0
If this guide helped you implement Cross App Access with SAML, explore these resources:
- 📘 Cross App Access Documentation: Official guides for configuring and managing Cross App Access in production.
- 🎙️ Developer Podcast on MCP and Cross App Access: Hear the backstory, use cases, and why this matters for developers.
Identity 101:
- What’s the Difference Between OAuth, OpenID Connect, and SAML?
- What are SAML, OAuth, and OIDC?
- Why You Should Migrate to OAuth 2.0 From Static API Tokens
- How to Get Going with the On-Demand SaaS Apps Workshops
Follow us on LinkedIn and X, and subscribe to our YouTube channel. Leave a comment below if you have any questions!
Okta Developer Blog Comment Policy
We welcome relevant and respectful comments. Off-topic comments may be removed.