An access token issued in one trust domain is useless, or dangerous, when a request has to continue into another domain with its own authorisation server. Teams usually solve this with shared secrets, long-lived service credentials or by forwarding the original token, and each of those loses either the user context or control over what the downstream domain can do. The IETF OAuth working group's Identity and Authorization Chaining Across Domains specification standardises a better pattern: exchange the token at home for a short-lived JWT authorisation grant, then redeem that grant at the other domain's authorisation server. This guide explains the flow, the trust set-up, claims transcription, the security rules and how to roll it out. It is written for IAM architects, API platform teams and anyone wiring workloads or AI agents across organisational or cloud boundaries.
Key takeaways
- Two standard steps, no new protocol. Chaining combines RFC 8693 Token Exchange in the home domain with the RFC 7523 JWT bearer grant in the target domain.
- The target domain keeps control. Domain B validates the grant against its own trust configuration and policy, then issues its own access token, so neither side has to accept the other's access tokens.
- The draft is at the RFC Editor, not yet an RFC. As checked on 27 October 2026, draft-ietf-oauth-identity-chaining-17 is in the RFC Editor queue as a Proposed Standard; confirm the final RFC number before you cite section numbers in contracts.
- Audience and lifetime are the main controls. A grant with one audience value, a lifetime of minutes and client authentication at domain B is far harder to replay than a forwarded access token.
- No refresh tokens downstream. Domain B should not issue refresh tokens in this flow, so access in domain B ends when domain A stops issuing grants.
What identity chaining solves
A trust domain here means a set of systems that share one authorisation server and one security policy: a company's internal API estate, a SaaS provider, a cloud tenant or a partner. Within one domain, a client gets an access token and calls resources. The problem starts when a service in domain A needs to call an API protected by domain B's authorisation server while preserving who the request is for.
Common answers before this specification each had a cost:
- Forwarding the original access token: domain B must trust domain A's tokens directly, and the token's audience is widened to cover both domains, which turns any leak into a multi-domain leak. RFC 9700 advises audience-restricted tokens precisely to stop this. See the OAuth 2.0 Security Best Current Practice Guide.
- A shared service account in domain B: the user context disappears, every request looks like the integration, and the credential is long-lived. This is classic NHI sprawl.
- A user consent flow per domain: works for interactive users, but not for back-end call chains, CI jobs or agents running inside a session.
Identity chaining keeps the user or workload identity, lets domain A decide whether the onward call is allowed, and lets domain B issue a token scoped to its own resources. The draft's appendix lists use cases including multi-cloud and hybrid services that need the original user context, CI pipelines reaching external resources without stored credentials, extending SSO to APIs, and cross-domain API calls such as an email client reaching a third-party calendar API.
The flow step by step
The specification describes four steps. Parameter names below are from draft -17.
- Discover domain B's authorisation server. The client finds it from the
authorization_serversproperty of the resource's RFC 9728 protected resource metadata (at/.well-known/oauth-protected-resource), from static configuration, or by another method. - Token exchange at domain A. The client calls domain A's token endpoint with
grant_type=urn:ietf:params:oauth:grant-type:token-exchange, presenting a token it already holds assubject_token. It must name domain B's authorisation server withresource(a URI) oraudience(a logical name), and may sendscopeto request a narrower grant. Domain A rejects unknown or unacceptable targets. - Domain A returns a JWT authorisation grant. Its
audmust identify domain B's authorisation server, and the draft recommends a single audience value. - JWT bearer grant at domain B. The client posts
grant_type=urn:ietf:params:oauth:grant-type:jwt-bearerwith the JWT asassertion, optionally withscopeor an RFC 8707resource. Domain B validates it under RFC 7523 Sections 3 and 3.1, identifies the subject, applies policy and returns an ordinary access token.
The client then calls domain B's resource server with that token. Domain B's resource server never sees domain A's tokens.
| Step | Endpoint | Key parameters | Who decides |
|---|---|---|---|
| Discovery | Resource metadata (RFC 9728) | authorization_servers, resource | Client, using trusted configuration |
| Token exchange | Domain A token endpoint | subject_token, subject_token_type, resource or audience, scope | Domain A: may this client take this subject to that domain? |
| Grant issued | Domain A response | JWT with aud = domain B AS, short exp | Domain A signs with keys domain B trusts |
| Assertion grant | Domain B token endpoint | grant_type jwt-bearer, assertion, client authentication | Domain B: is the issuer trusted, is the subject known, is policy met? |
| API call | Domain B resource server | Domain B access token | Domain B resource server |
Trust set-up between domains
The protocol is simple; the trust relationship is where the work is. Domain B must hold domain A's signing keys, either configured directly or fetched from domain A's jwks_uri. Decide and document the following before any traffic flows:
- Issuer allow list: domain B accepts grants only from named issuers, compared by exact string as RFC 7523 requires for
iss. - Key distribution: prefer a published JWKS with key IDs so domain A can rotate signing keys without a coordinated change window. Pinning a single static key makes rotation an outage.
- Client registration at both ends: the client authenticates to domain A for the exchange and to domain B for the assertion grant. The draft points to RFC 9700 Section 2.5 for client authentication; asymmetric methods such as
private_key_jwtor mTLS avoid shared secrets. See the mTLS Guide. - Subject mapping: agree how a user or workload in domain A maps to an account in domain B (email, pairwise identifier, employee number). Domain B must deny the request if it cannot identify the subject.
- Scope ceiling: agree the maximum scopes domain A may request for domain B, and have domain B enforce that ceiling regardless of what the grant claims.
- Discovery trust: if clients discover domain B's authorisation server from resource metadata, they must check that the
resourcevalue matches the URL they asked for, as RFC 9728 requires, or an attacker-controlled resource can steer them to an attacker's authorisation server.
Federation of this kind is a contractual and operational relationship as much as a technical one. See the Federation and Trust Relationships Guide and the OpenID Federation and Trust Chains Guide for managing trust at scale.
Claims transcription and data minimisation
The draft deliberately does not define the grant's claim set beyond requiring an audience and a subject domain B can identify. Instead it allows both authorisation servers to add, change or remove claims, which it calls claims transcription. The stated reasons are worth adopting as design rules:
- Subject mapping: translate the identifier into one domain B understands, rather than leaking domain A's internal user ID.
- Data minimisation: strip claims domain B does not need, such as group memberships, department or internal risk scores. This matters for UK GDPR and similar regimes when the domains belong to different controllers.
- Scope control: downscope, and check that requested scopes never exceed those of the subject token.
- Claim propagation: carry agreed claims (for example an authentication context or a tenant) into domain B's access token so its resource servers can use them.
Because the format of transcribed claims is not standardised, write a short claims contract per domain pair: claim name, meaning, source, and whether domain B may rely on it for authorisation. Where delegation matters, the RFC 8693 act claim records the acting party; see the OAuth Token Exchange and Delegation Guide for delegation versus impersonation semantics.
Security rules that matter in production
| Risk | What the draft says | Implementation choice |
|---|---|---|
| Grant replay | Grants are bearer credentials; use short lifetimes, single use and client authentication at domain B | Lifetime of a few minutes; track jti at domain B where you can; require client authentication on the assertion grant |
| Token theft downstream | Follow RFC 9700 on sender constraining; domain A may pass the client's key as requested_cnf so domain B binds its token | DPoP or mTLS-bound access tokens in domain B for high-value APIs. See the DPoP Guide |
| Session outliving revocation | Domain B SHOULD NOT issue refresh tokens; clients re-present or request a new grant | Do not enable refresh tokens on the jwt-bearer grant for chained clients |
| Lateral movement | Domain A should verify the client is authorised to present the subject token | Bind exchange permission to client and target pairs, not to any authenticated client |
| Over-broad audience | Grant aud must identify domain B; single value recommended | Reject multi-audience requests at domain A |
| Privilege creep | Scopes must not exceed the subject token's | Enforce a per-pair scope ceiling at both authorisation servers |
Treat the signing key that domain A uses for grants as a crown-jewel credential: anyone holding it can mint grants that domain B will honour for any mapped user. Keep it in an HSM or managed KMS, separate from the key that signs ordinary access tokens if your product allows.
Choosing chaining versus other patterns
Identity chaining is not always the right tool. Use the table to decide.
| Situation | Better fit | Why |
|---|---|---|
| Calls stay inside one authorisation server's domain | RFC 8693 token exchange alone, or Transaction Tokens for internal call chains | No second authorisation server to satisfy. See the OAuth Transaction Tokens Guide |
| Two SaaS apps share an enterprise IdP and the IdP should govern app-to-app access | Identity Assertion JWT Authorization Grant (ID-JAG), a profile of chaining | The IdP issues the grant and applies admin policy. See the Identity Assertion JWT Authorization Grant Guide |
| Pure machine-to-machine call with no user context | Client credentials, or workload identity federation | No subject to carry. See the Workload Identity Federation Guide |
| Interactive user, low call volume, domain B wants explicit consent | Authorisation code flow at domain B | Consent is a feature here, not friction |
| Workloads across clouds with their own identity documents | Chaining, with workload credentials as the subject token | Keeps the original workload identity, avoids static keys |
Small organisations: you will usually be domain B, receiving grants from a customer's or partner's authorisation server. Focus on the issuer allow list, subject mapping and refusing refresh tokens. Large organisations: you will often run both sides across business units or clouds. Centralise the per-pair trust register and claims contracts, and make onboarding a new domain pair a reviewed change.
How to implement
- Inventory cross-domain calls. Find every place a service or integration holds a credential for another domain: stored partner API keys, shared service accounts, forwarded tokens. Each is a candidate.
- Check product support. Confirm your authorisation servers support RFC 8693 exchange with
resourceoraudience, and the RFC 7523 jwt-bearer grant with issuer allow lists. The draft adds an authorisation server metadata parameter,identity_chaining_requested_token_types_supported, for advertising supported token types; support will vary while the RFC is pending. - Agree the trust and claims contract for the first domain pair: issuer, JWKS location, subject mapping, scope ceiling, grant lifetime, logging fields.
- Build in a test tenant. Test negative cases first: wrong audience, expired grant, unknown issuer, unmapped subject, requested scope above the ceiling, replayed
jti. Every one must fail withinvalid_grantor a policy denial. - Pilot on one low-risk integration running in parallel with the old credential, comparing results and latency for two to four weeks.
- Cut over and retire the old credential. Revoke the shared secret or service account; leaving it active defeats the purpose.
- Roll back safely. Keep the old path disabled but documented for the pilot period. Rolling back means re-enabling a credential, so time-box it and record the decision.
Detection and measurement
Log at both authorisation servers and correlate on the grant's jti and subject:
- Domain A: every token exchange with client ID, subject, requested target, granted scope and decision.
- Domain B: every jwt-bearer request with issuer,
jti, mapped account, granted scope and any denial reason. - Alerts: a
jtipresented twice, grants from an issuer not on the allow list, exchange requests for targets a client has never used, spikes in subject mapping failures, and any refresh token issued on a chained grant.
Metrics that show the programme is working:
- Number of cross-domain integrations still using static credentials, trending to zero.
- Median and maximum grant lifetime issued (target: minutes).
- Percentage of chained access tokens that are sender-constrained.
- Exchange and assertion denial rate, with reasons, to spot misconfiguration and probing.
- Time from offboarding a user in domain A to their last successful call in domain B.
Framework mapping
| Framework | Reference | Relevance |
|---|---|---|
| NIST SP 800-53 Rev 5 | AC-4 Information Flow Enforcement; IA-8 Identification and Authentication (Non-organizational Users); IA-9 Service Identification and Authentication; SA-9 External System Services; SC-23 Session Authenticity | Controlled flow of identity between domains and authentication of external services |
| NIST CSF 2.0 | PR.AA-01, PR.AA-03, PR.AA-05; GV.SC-07 | Identity and credential management, authentication, least-privilege authorisation, supplier risk |
| ISO/IEC 27001:2022 Annex A | 5.15 Access control; 5.17 Authentication information; 5.19 Information security in supplier relationships; 8.5 Secure authentication | Policy and supplier controls for cross-organisation access |
| CIS Controls v8.1 | Control 6 Access Control Management; Control 15 Service Provider Management | Centralised access and service provider oversight |
| MITRE ATT&CK | T1550.001 Application Access Token; T1528 Steal Application Access Token; T1199 Trusted Relationship | Techniques that short, audience-bound grants make harder |
Common failure patterns
- Storing long-lived downstream tokens instead of chaining. Integrations that keep refresh tokens for other domains create a treasure store. In the Salesloft Drift breach, OAuth access and refresh tokens held for customers' Salesforce and Google Workspace integrations were stolen from the vendor's AWS environment and used to export customer data. Short-lived, per-request grants with no downstream refresh tokens shrink that store.
- Accepting any issuer whose keys you can fetch. Domain B must allow-list issuers, not trust whatever JWKS a grant's
isspoints to. - Multi-audience grants. One grant valid at several authorisation servers lets one compromised downstream replay it elsewhere.
- Subject mapping on mutable attributes. Mapping on email alone breaks on rename and enables account takeover when addresses are reused. Prefer a stable pairwise identifier, with email only as a fallback agreed in the claims contract.
- Leaving the old shared credential in place. The chained flow works, nobody revokes the service account, and the attacker uses the service account.
- Logging whole grants. A logged grant is a usable bearer credential until it expires. Log
jti, issuer and subject, not the JWT.
Practitioner checklist
- List every cross-domain integration and the credential it uses today.
- Confirm both authorisation servers support RFC 8693 exchange and the RFC 7523 jwt-bearer grant.
- Write a trust and claims contract per domain pair: issuer, JWKS, subject mapping, scope ceiling, lifetime.
- Require a single audience and a lifetime of minutes on every grant.
- Require client authentication at domain B, using asymmetric methods.
- Disable refresh tokens on chained jwt-bearer grants.
- Sender-constrain downstream access tokens for sensitive APIs.
- Correlate exchange and assertion logs on
jtiand alert on reuse. - Revoke the legacy credential once each integration is cut over.
- Track the draft until it is published as an RFC and update references.
Standards and references
- IETF: OAuth Identity and Authorization Chaining Across Domains (draft-ietf-oauth-identity-chaining)
- IETF: RFC 8693 OAuth 2.0 Token Exchange
- IETF: RFC 7523 JWT Profile for OAuth 2.0 Client Authentication and Authorization Grants
- IETF: RFC 9728 OAuth 2.0 Protected Resource Metadata
- IETF: Identity Assertion JWT Authorization Grant (draft-ietf-oauth-identity-assertion-authz-grant)
- IETF: Transaction Tokens (draft-ietf-oauth-transaction-tokens)
Related NHI Mgmt Group resources: OAuth Token Exchange and Delegation Guide · Identity Assertion JWT Authorization Grant Guide · OAuth Transaction Tokens Guide · Federation and Trust Relationships Guide