Integration guides

Cross App Access (XAA)

World IdP supports consumer-controlled identity delegation through its Cross App Access (XAA) profile of the Identity Assertion JWT Authorization Grant draft, revision 06 (opens in a new tab) (ID-JAG, work in progress). A user connects an agent host and chooses the apps it may access. The host can then obtain credentials for those apps without separate World ID authentication for each app. Each app's authorization server issues its own access tokens and controls API permissions. Apps can adopt XAA alongside their existing sign-in.

Requirements

Agent hosts request openid offline_access and receive a refresh token, which each refresh replaces.

The agent host must support XAA with World IdP as its identity provider. Check this before integrating.

Hosts may register through Client ID Metadata Documents (CIMD), using public clients or private_key_jwt client authentication. A host that uses device authorization must be confidential. A CIMD host that starts device authorization needs private_key_jwt and the device-code grant in its metadata. A host's login accepts any World ID account unless its metadata lists default_acr_values with classes from Accepted accounts.

World IdP's profile differs from revision 06 in two ways: it accepts public hosts at the token exchange (Section 4.3.3 (opens in a new tab)), and it returns invalid_grant when the subject token fails validation, where revision 06 uses invalid_request (Section 4.3.4.3 (opens in a new tab)).

Check World IdP's discovery document for XAA availability. It advertises offline_access, refresh, and ID-JAG exchange only while XAA is enabled. When disabled, requests for offline_access receive invalid_scope; refresh and ID-JAG exchange return HTTP 400 unsupported_grant_type.

Your app's authorization server must accept ID-JAGs issued by World IdP and issue access tokens for your MCP server.

Configure your authorization server

Configure your authorization server to trust World IdP, https://auth.world.org. Accept the ID-JAG JWT bearer grant and apply the draft's processing rules (opens in a new tab), with your authorization-server issuer as audience and RS256 signing keys from discovery's jwks_uri.

When a host authenticates, bind client_id to the authenticated host. Public hosts send the ID-JAG without client authentication or key binding, which revision 06 does not allow (Section 4.4 (opens in a new tab)). To serve them, identify the host by the ID-JAG's client_id claim. To serve only confidential hosts, require client authentication.

Hosts and authorization servers must agree on the client identifier; for a host using a Client ID Metadata Document (CIMD), this is the exact HTTPS metadata URL. Register the host at your authorization server with its own credentials, and never accept a client secret that World IdP issued to it.

The ID-JAG's sub is the same pairwise subject World IdP issues to your app in ID tokens. Its auth_time, acr, and amr describe the user's original World ID authentication, not a fresh one. Match accounts by (iss, sub), as for ID tokens. Your authorization server applies its own scope policy and issues the access token used to call your MCP server.

Publish RFC 8414 metadata at your authorization server's well-known location, including the ID-JAG draft's authorization_grant_profiles_supported extension:

{
  "issuer": "https://app.example",
  "grant_types_supported": ["urn:ietf:params:oauth:grant-type:jwt-bearer"],
  "authorization_grant_profiles_supported": ["urn:ietf:params:oauth:grant-profile:id-jag"]
}

Enroll your app

Register your app in the developer portal (opens in a new tab). As its owner, use the active app's client settings to submit your authorization-server issuer and the resource URLs of your MCP servers. That issuer identifies the server that issues your access tokens; it is separate from your app's identity sector at World IdP.

World IdP reviews your app's authority over its identity sector, issuer, and resources before users can select it. Enrollment uses the metadata above; no additional verification document or custom metadata field is required. XAA review is independent of catalog publication, and the app picker uses the name recorded at approval.

Several apps can share an authorization server, with separate resources and permissions. A resource URL may be approved for only one app; pending or rejected submissions do not reserve it. World IdP cannot enroll as an app's target authorization server.

Changing the issuer or resources requires a new review. Resource changes preserve saved app permissions; changing the issuer requires renewed user permission. Disabling the app or withdrawing approval stops new ID-JAG exchanges; an exchange already in progress may complete. After a rejection, you can request review again without changing the issuer or resources, and users keep their app selections.

Connect the agent

The host opens World ID authentication and consent, where the user selects the apps it may access. A new app starts unselected, and users can change their selection later.

A host can connect any World ID account. Your app's accepted accounts decide which accounts it receives ID-JAGs for: Orb admits Orb accounts, Selfie Check also admits Selfie Check accounts, and Any account admits every account. Consent marks apps that do not accept the user's account, and ID-JAG requests for them return access_denied.

A host's connection expires after 180 days without a successful refresh or ID-JAG exchange. Each one renews that deadline and keeps the original authentication context. The host reconnects interactively after expiry or revocation. Device consent requires an account session authenticated at or after the device request began.

Permissions belong to the exact host client ID, which for a CIMD host is its metadata URL. A new URL, even on the same hostname, is a new host, so hosts should keep it stable. Sessions using the same client ID share app permissions, and reconnecting preserves saved choices. Temporarily unavailable apps retain those choices while their authorization-server issuer stays unchanged.

Manage access

Users can remove an app's permission or disconnect the host at any time. Removing a permission stops new ID-JAG exchanges for that app, and disconnecting stops them for every app; an exchange already in progress may complete. Issued ID-JAGs expire within five minutes, and your access tokens follow your own expiry and revocation policy.