Ena OAuth 2.0 Token Exchange Profile for Chaining Identity and Authorization
Version: 1.0 - draft 01 - 2025-10-17
Abstract
The OAuth 2.0 framework defines mechanisms that allow users (resource owners) to delegate access rights to protected resources for the applications they use.
This document specifies solutions for chaining OAuth 2.0 identity and authorization in scenarios where calls to protected resources trigger additional calls, or where calls cross domain boundaries.
Table of Contents
-
Protected Resource Acting as an Client
2.1. Problem Statement
2.2. Solution Overview
2.3.1. Processing Requirements
2.4.1. The Actor Claim
2.5. Examples
-
Accessing Protected Resources in Other Domains
3.1. Problem Statement
3.2. Solution Overview
3.2.1. Domain Trust Relationships and Prerequisites
3.3. Token Exchange
3.3.1. Token Exchange Request
3.3.2. Inbound Token Requirements
3.3.3. Processing Requirements
3.3.4. Token Exchange Response and JWT Contents
3.4. Authorization Grant Requirements
3.4.1. Access Token Request According to RFC7523
3.4.2. Processing of JWT Authorization Grant
3.4.3. Token Response
3.5. Additional Features and Advanced Topics
3.5.1. Scope Mapping Across Domains
3.5.2. Transcription of User Identity Claims
3.6. Examples
-
General Token Exchange Requirements and Considerations
4.1. The Resource and Audience Parameters
4.2. Subject Token Requirements and Considerations
4.2.1. Issuing a Token Usable for Token Exchange
4.2.2. Processing Requirements for a Subject Token
4.3. Token Exchange and the User and Resource Owner Distinction
-
5.1. Normative References
1. Introduction
The "OAuth 2.0 Token Exchange" specification, [RFC8693], defines a generic extension to OAuth 2.0 that allows an entity to call an OAuth 2.0 authorization server acting as a Security Token Service (STS) in order to exchange a token in its possession for another token. While token exchange is a powerful tool for addressing many OAuth 2.0-related challenges, a generic specification such as [RFC8693] requires profiling to achieve interoperability and to avoid introducing security risks.
This specification profiles the use of OAuth 2.0 Token Exchange for two common use cases where a structured and secure method of applying OAuth 2.0 has not previously been defined.
-
Protected Resource Acting as a Client – A protected resource may, in order to fulfil a request, need to act as an OAuth 2.0 client and make another call that requires an access token. This use case is described in Section 2.
-
Accessing Protected Resources in Other Domains – Entities may need to access resources outside their own domain, where a different authorization server and trust model apply, and in many cases, a different user authentication model is used. This use case is described in Section 3.
Common to both use cases is that each API, or protected resource, requires the presentation of a valid access token that conveys some or all of the user's delegated access rights to the protected resource. To enable this delegation, the user's identity must be established and chained across subsequent calls.
The problem statements therefore do not include the use of the client credentials grant, where one service calls another without the involvement of a user or resource owner. Such usage is not affected by the chaining challenges described in this document and is therefore out of scope for this specification.
Note: Section 1.5 of [Ena.OAuth2.Profile] describes the distinction between a user and a resource owner, and in some OAuth 2.0 deployments, the user is not the actual resource owner. This profile covers the following cases:
-
The user is the resource owner and, when directed to the authorization server, delegates access to a client for accessing a protected resource owned by the user.
-
A user (for example, an employee) uses an application (the client) that retrieves a protected resource owned by someone other than the user (for example, the user’s organization or another legal entity), but the user’s access is authorized according to the resource’s access policy. In such cases, the user participates in the OAuth 2.0 flow to verify their identity and confirm that they are authorized.
The requirements for the use of OAuth 2.0 token exchange may differ depending on whether the user is the actual resource owner. Where this is relevant, this profile explicitly specifies under which circumstances a given requirement applies. See Section 4.3, Token Exchange and the User and Resource Owner Distinction.
1.1. Requirements Notation and Conventions
The keywords “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” are to be interpreted as described in [RFC2119].
These keywords are capitalized when used to unambiguously specify requirements over protocol features and behavior that affect the interoperability and security of implementations. When these words are not capitalized, they are meant in their natural-language sense.
2. Protected Resource Acting as an Client
2.1. Problem Statement
The simple illustration below shows a typical use of the OAuth 2.0 authorization code grant, where an application (OAuth 2.0 client) obtains an access token from the authorization server to access an API (protected resource) on behalf of a user interacting with the application.
But what happens if the implementation of the API needs to make a backend call to a second API in order to construct a response to the API request?
In this scenario, the first API will act as an OAuth 2.0 client against the second API, but how will it acquire the access token to pass along in the call?
Firstly, let's determine why the access token it received in the call from the application cannot simply be forwarded:
-
The audience for this access token is set to be the first API and according to access token processing rules (see Section 6.1 of [Ena.OAuth2.Profile]) the second API would reject this token since it is not intended for it.
-
The
client_id
claim for the access token is set to the identifier of the client making the request which in our case is the application. -
The scope(s) issued for the first access token may differ from the scope requirements of the second API.
-
If the "Demonstrating Proof of Possession - DPoP", [RFC9449], security feature is used within the OAuth-deployment, the first API cannot simply forward the DPoP-header to the second API since it is a one-time use header that is also bound to the exact URL of the (orginal) request.
Some deployments that do not use DPoP forward access tokens between services in a call chain. In such cases, the access token either contains multiple audience values or all invoked services are treated as the same entity. Furthermore, the initial client identifier is passed along the chain, which breaks traceability. Entities conformant with this profile MUST NOT rely on such shortcuts.
The following sub-sections specify how OAuth 2.0 Token Exchange, as defined in [RFC8693], can be used by a protected resource to obtain a new access token based on a previously received one before acting as an OAuth 2.0 client to call another service.
2.2. Solution Overview
The sequence diagram below illustrates the role of OAuth 2.0 Token Exchange during chained API-calls.
sequenceDiagram
autonumber
actor User as User
participant Service as Application<br/>(Client)
participant AsA as Authorization Server A
participant ApiA as Protected Resource<br/>API A
participant ApiB as Protected Resource<br/>API B
User-->>Service: Action ...
Service-->>+User: Redirect
User->>-AsA: Authorization Request
User-->AsA: Authenticate (and possibly consent)
AsA-->>+User: Redirect
User->>-Service: Authorization Response w. code
Service->>+AsA: Token Request w. code
AsA->>-Service: Token Response w. Access Token
Service->>+ApiA: Make API call<br/>Include Access Token
Note over ApiA: API A will have to invoke API B<br/>in order to process API-call
ApiA->>+AsA: Token Exchange Request
AsA->>-ApiA: Token Exchange Response<br/>with Access Token
ApiA->>+ApiB: Make API call<br/>Include new Access Token
ApiB->>-ApiA: API response
ApiA->>-Service: API response
Service-->>User: Response ...
Steps 1 through 9 represent a standard OAuth 2.0 authorization code flow, where the application (client) obtains an access token by directing the user to the authorization server, where the user authenticates and the application’s access rights are authorized. The application then uses the issued access token to access the protected resource, API A. The protected resource validates the supplied access token before starting to process the request.
However, in order for API A to process the API-call and to put together a response, it needs to make a call to an underlying resource, API B.
In order to obtain a valid access token for API B, API A acts as an OAuth 2.0 client towards the authorization server. Instead of prompting the user again or forwarding the original token, API A uses OAuth 2.0 Token Exchange [RFC8693] to present the inbound access token it received from the application and requests a new access token intended for API B (steps 10 and 11).
This mechanism ensures that:
- The user’s identity and authorization context are preserved across the chained call.
- The newly issued access token has the correct audience, namely API B, and the appropriate scopes required for the operation.
- API A’s client identity is visible in the transaction, providing accountability and auditability.
- Security features such as DPoP bindings remain valid, since the access token is freshly minted for the target resource.
By using token exchange, API A does not need to manage or impersonate the original client. Instead, it formally assumes the role of an OAuth 2.0 client, bound by the same rules as any other client when requesting access tokens. This maintains a clear separation of concerns: the application acts as a client in relation to API A, and API A acts as a client in relation to API B.
This solution also strengthens traceability, since the resulting access token clearly reflects both the identity of the user (as chained from the inbound token) and the identity of API A as the requesting client. Downstream services can therefore distinguish whether a request originates directly from the user’s application or from another protected resource acting on behalf of the user.
In the following sections, the exact requirements for the token exchange request, processing rules, and response are defined.
2.3. Token Exchange Request
A protected resource that needs to act as a client in order to call another protected resource MUST perform an OAuth 2.0 token exchange request in accordance with [RFC8693]. The inbound access token received from the original client MUST be supplied as the subject_token
.
The token exchange request MUST include:
-
grant_type
with the valueurn:ietf:params:oauth:grant-type:token-exchange
. -
subject_token
containing the inbound access token. -
subject_token_type
with the valueurn:ietf:params:oauth:token-type:access_token
. -
A target indicator identifying the downstream protected resource, either
resource
oraudience
. See Section 4.1 for further requirements.
If ascope
value is provided from which the authorization server can deduce the protected resource, the target indicator MAY be omitted.
Clients SHOULD include:
-
requested_token_type
with the valueurn:ietf:params:oauth:token-type:access_token
.- Also see the text about "Servers supporting multiple profiles" in Section 2.3.1 below.
Clients MAY include:
-
scope
if specific scopes are required by the downstream protected resource.- In deployments where the subject (user) is the actual resource owner, any requested scopes MUST have been consented to by the user during the original authorization and MUST NOT exceed what was authorized. See Section 4.3, Token Exchange and the User and Resource Owner Distinction.
Multiple resource
or audience
parameters MAY be included to indicate the intended use of the resulting access token at multiple protected resources, or as stated in Section 6.1.1 of [Ena.OAuth2.Profile], to support alternative representations of a protected resource as audience values.
Client authentication at the token endpoint MUST follow the requirements given in [Ena.OAuth2.Profile].
2.3.1. Processing Requirements
When processing a token exchange request, the authorization server MUST:
-
Validate the inbound access token according to Section 4.2.2, Processing Requirements for a Subject Token.
-
Verify that the requesting entity is authorized to perform token exchange.
-
Enforce that at least one target indicator (
resource
oraudience
) is present, unless ascope
value is provided from which the authorization server can deduce the target service.-
If neither is present, the request MUST be rejected with
invalid_request
. -
If multiple values are present, the authorization server MUST process them according to local policy and the requirements in [Ena.OAuth2.Profile] (for example, supporting multiple audiences or alternative identifiers for the same resource as described in Section 6.1.1).
-
-
Verify that each requested target corresponds to a registered downstream protected resource.
-
In deployments where the subject (user) is the actual resource owner, each requested
scope
value MUST be consistent with what was originally authorized by the user. Any scope that has not been granted by the user MUST be rejected. See Section 4.3. -
In deployments where the subject (user) is not the resource owner, the authorization server MUST assert, for each requested
scope
value, that the user and client are entitled to obtain this scope for the given target(s); otherwise, the scope MUST be rejected. See Section 4.3. -
Assert that
requested_token_type
isurn:ietf:params:oauth:token-type:access_token
, or if it is omitted, apply the logic from "Servers supporting multiple profiles" below.
Servers supporting multiple profiles: An authorization server deployment may support token exchange both within its own domain (as described in this section) and in other scenarios that involve different domains (described in Section 3). In such cases, the requested_token_type
parameter MUST be used to distinguish which type of token exchange the client is requesting. When requested_token_type
is urn:ietf:params:oauth:token-type:access_token
, the server MUST process the request according to this section and issue an access token intended for the indicated protected resource(s). When requested_token_type
is urn:ietf:params:oauth:token-type:jwt
, the server MUST process the request according to the rules specified in Section 3 and issue a JWT authorization grant for use at another authorization server. If the parameter is omitted and the server cannot unambiguously determine the intended profile from context, it MUST reject the request with invalid_request
.
2.4. Token Exchange Response
Upon successful validation, the authorization server MUST issue a new access token in response to the token exchange request. The issued access token MUST follow the requirements stated in Section 6.1 of [Ena.OAuth2.Profile] with the following extensions and clarifications:
-
The access token JWT MUST include an
aud
(audience) claim corresponding to the requested downstream protected resource (expressed with theresource
oraudience
request parameter).- The authorization server MAY include additional audience values representing the same resource, for example to support legacy deployments or alternative identifiers not aligned with the entity naming specified in [Ena.OAuth2.Profile].
-
The access token JWT MUST carry the same
sub
(end-user identity) as the inbound access token, thereby preserving the (delegated) user authorization. -
The access token JWT MUST include all user identity claims from the inbound access token that the receiving entity is authorized to receive.
- The authorization server MUST NOT include any user identity claims that the receiving entity is not authorized to receive.
-
If the inbound access token contains claims that provide information about the user’s authentication context, such as
acr
,amr
, orauth_time
, these claims MUST be preserved and included in the issued access token JWT. -
In order to provide accountability and auditability, the
act
claim SHOULD be included, containing both the current actor (the entity that requested the access token) and the originating actor(s). The actor MUST be represented using thesub
claim, consistent with [RFC8693]. See Section 2.4.1 below. -
The access token JWT MUST contain only those scopes that are permitted for the requesting protected resource and relevant to the downstream protected resource.
-
The access token MUST be bound to proof-of-possession mechanisms (such as [RFC9449] DPoP) if such mechanisms are in use in the deployment.
The response MUST be encoded as JSON according to Section 2.2.1 of [RFC8693] and include at least the following elements:
-
access_token
– The issued access token as defined above. -
issued_token_type
– The token type MUST be set tourn:ietf:params:oauth:token-type:access_token
. -
token_type
– Specifies the method of using the issued access token. MUST be set toBearer
. -
expires_in
– The validity of the issued access token. The value is dependent on deployment policy and out of scope for this profile.
Furthermore, the scope
parameter is optional according to [RFC8693] if the scope(s) issued were the same as the requested scope(s). However, for simplicity and to improve interoperability, for entities compliant with this profile its use is RECOMMENDED in all cases.
Unless overridden by local policy, authorization servers compliant with this profile MUST NOT issue refresh tokens for token exchange in the context of identity and authorization chaining.
2.4.1. The Actor Claim
The act
(actor) claim provides accountability and auditability by recording which entity performed the token exchange. This claim enables downstream protected resources to distinguish between the end-user identity (sub
) and the chain of actors that acted on behalf of the user.
As defined in Section 4.1 of [RFC8693], the act
claim may be a nested structure to represent multiple actors. Under this profile:
-
The authorization server SHOULD include the
act
claim in access tokens issued through token exchange. -
If included, the
act
claim MUST contain asub
claim identifying the entity that requested the token exchange. -
The first
sub
claim under theact
claim will always be identical to theclient_id
claim included in the access token, as required by Section 6.1 of [Ena.OAuth2.Profile]. -
When multiple exchanges occur, the authorization server MUST preserve all previous actors by nesting them according to [RFC8693].
-
The resulting
act
chain MUST begin with the original client application and continue with each intermediate protected resource that performed a token exchange. -
Consistent with [RFC8693], the contents of the
act
claim MUST NOT be used for authorization decisions. It is only intended for accountability, auditability, and traceability.
Example
Below is a simplified JWT payload of an access token issued by https://as.example.com
to be used at https://api2.example.com
.
{
"iss": "https://as.example.com",
"aud": "https://api2.example.com",
"sub": "user-1234",
"acr": "http://id.elegnamnden.se/loa/1.0/loa3",
"client_id": "https://api1.example.com",
"act": {
"sub": "https://api1.example.com",
"act": {
"sub": "https://app.example.com"
}
},
"scope": "api-read",
"jti": "987ui87665456",
"nbf": 1695379200,
"iat": 1695379200,
"exp": 1695382800
}
In this example:
- The
sub
claim identifies the end-user (user-1234) and theacr
claim tells under which authentication context class the user was authenticated. - The
client_id
claim identifieshttps://api1.example.com
, the protected resource acting as a client in the token exchange. - The first
sub
claim under theact
claim is alsohttps://api1.example.com
, and therefore always equals theclient_id
. - The nested
sub
claim under theact
claim identifieshttps://app.example.com
, the original client application. - The
aud
claim identifieshttps://api2.example.com
, the downstream protected resource.
This chaining ensures that all involved actors are visible to the downstream service, while authorization decisions remain based only on the standard claims (sub
, aud
, scope
, etc.).
2.5. Examples
This section provides a non-normative, end-to-end illustration of token exchange, aligned with the "Ena OAuth 2.0 Interoperability Profile", [Ena.OAuth2.Profile].
The example illustrates:
-
The inbound access token (JWT) from the application,
https://app.example.com
, to the first protected resource,https://api1.example.com
. -
The full HTTP token exchange request that the first protected resource,
https://api1.example.com
, sends to the authorization server,https://as.example.com/token
(including a signedclient_assertion
). -
The HTTP response, and the newly issued access token (JWT) for the second protected resource,
https://api2.example.com
.
For readability, long values are folded and signatures are abbreviated. All examples use the scope api-read
.
Inbound Access Token (JWT):
Access token presented by the application (https://app.example.com
) to the first protected resource (https://api1.example.com
):
{
"iss": "https://as.example.com",
"aud": ["https://api1.example.com", "https://as.example.com"],
"sub": "user-1234",
"acr": "http://id.elegnamnden.se/loa/1.0/loa3",
"client_id": "https://app.example.com",
"scope": "api-read",
"jti": "inbound-1234-unique-jwt-id",
"nbf": 1695375550,
"iat": 1695375600,
"exp": 1695379200
}
Note that the authorization server has issued the access token with its own issuer identifier among the
aud
values. See Section 4.2.1, Issuing a Token Usable for Token Exchange.
Token Exchange Request:
The protected resource https://api1.example.com
acts as an OAuth 2.0 client and calls the AS token endpoint for a token exchange request, authenticating with private_key_jwt
. The inbound access token above is supplied as the subject_token
and a new access token is requested for the audience https://api2.example.com
.
HTTP request:
POST /token HTTP/1.1
Host: as.example.com
Content-Type: application/x-www-form-urlencoded
grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Atoken-exchange&
subject_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2FzLmV4YW1wbGUu \
Y29tIiwiYXVkIjoiaHR0cHM6Ly9hcGkxLmV4YW1wbGUuY29tIiwic3ViIjoidXNlci0xMjM0IiwiY2xpZW50X \
2lkIjoiaHR0cHM6Ly9hcHAuZXhhbXBsZS5jb20iLCJzY29wZSI6ImFwaS1yZWFkIiwianRpIjoiaW5ib3VuZC \
0xMjM0LXVuaXF1ZS1qd3QtaWQiLCJuYmYiOjE2OTUzNzU1NTAsImlhdCI6MTY5NTM3NTYwMCwiZXhwIjoxNjk \
1Mzc5MjAwfQ.MEUCIQDt...&
subject_token_type=urn%3Aietf%3Aparams%3Aoauth%3Atoken-type%3Aaccess_token&
audience=https%3A%2F%2Fapi2.example.com&
scope=api-read&
client_id=https%3A%2F%2Fapi1.example.com&
client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&
client_assertion=eyJhbGciOiJSUzI1NiIsImtpZCI6ImtpZC0wMDEiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJ \
odHRwczovL2FwaTEuZXhhbXBsZS5jb20iLCJzdWIiOiJodHRwczovL2FwaTEuZXhhbXBsZS5jb20iLCJhdWQi \
OiJodHRwczovL2FzLmV4YW1wbGUuY29tL3Rva2VuIiwianRpIjoiYTMtMTIzNC11bmlxdWUtand0LWlkIiwib \
mJmIjoxNjk1Mzc1NTUwLCJpYXQiOjE2OTUzNzU2MDAsImV4cCI6MTY5NTM3NTkwMH0.MIIB...
For reference, the decoded client_assertion
(private_key_jwt
) components:
JOSE header:
{
"alg": "RS256",
"kid": "kid-001",
"typ": "client-authentication+jwt"
}
JWT claims:
{
"iss": "https://api1.example.com",
"sub": "https://api1.example.com",
"aud": "https://as.example.com",
"jti": "a3-1234-unique-jwt-id",
"nbf": 1695375550,
"iat": 1695375600,
"exp": 1695375900
}
Token Exchange Response:
HTTP response:
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
{
"access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6ImtpZC0wMDEiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodH \
RwczovL2FzLmV4YW1wbGUuY29tIiwiYXVkIjoiaHR0cHM6Ly9hcGkyLmV4YW1wbGUuY29tIiwic3ViIjoidXNlci0x \
MjM0IiwiYWN0Ijp7InN1YiI6Imh0dHBzOi8vYXBpMS5leGFtcGxlLmNvbSIsImFjdCI6eyJzdWIiOiJodHRwczovL2 \
FwcC5leGFtcGxlLmNvbSJ9fSwic2NvcGUiOiJhcGktcmVhZCIsImp0aSI6Im5ldy0xMjM0LXVuaXF1ZS1qd3QtaWQi \
LCJuYmYiOjE2OTUzNzkyMDAsImlhdCI6MTY5NTM3OTIwMCwiZXhwIjoxNjk1MzgyODAwfQ.Fh0B...",
"issued_token_type": "urn:ietf:params:oauth:token-type:access_token",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "api-read"
}
Newly Issued Access Token (JWT):
Decoded claims of the issued access token intended for https://api2.example.com
:
{
"iss": "https://as.example.com",
"aud": "https://api2.example.com",
"sub": "user-1234",
"acr": "http://id.elegnamnden.se/loa/1.0/loa3",
"client_id": "https://api1.example.com",
"act": {
"sub": "https://api1.example.com",
"act": {
"sub": "https://app.example.com"
}
},
"scope": "api-read",
"jti": "new-1234-unique-jwt-id",
"nbf": 1695379200,
"iat": 1695379200,
"exp": 1695382800
}
3. Accessing Protected Resources in Other Domains
3.1. Problem Statement
The previous section described the challenge of identity and authorization chaining for services within the same domain, i.e., where the same trust model and authorization server are used. However, applications may also need to access resources outside their own domain, where a different authorization server and trust model apply, and in many cases, a different user authentication model.
Given this problem statement, the main challenges are:
- The user cannot simply be redirected to the authorization server in the second domain, since that server has no way of authenticating the user.
- An access token issued by the authorization server in the first domain will not be accepted by protected resources in the second domain.
The solution to the above challenges requires establishing a trust relationship between the authorization servers in the respective domains. This trust enables the authorization server in the first domain to issue a statement intended for the authorization server in the second domain, allowing clients in the first domain to obtain access tokens that can be used in the second domain.
3.2. Solution Overview
Note: The draft "OAuth Identity and Authorization Chaining Across Domains", [Draft.ID-Chaining], focuses on solving the problem described above. Future versions of this profile will reference this specification if and when it reaches RFC status. Until then, the draft is informational and no references will be made to it.
The solution for identity and authorization chaining within the same trust domain involves exchanging an access token for another access token containing the correct audience and scope values. However, when a call is made to another trust domain, the output from the token exchange cannot be an access token usable at the intended protected resource. This is because:
- The authorization server in the originating domain does not have knowledge of protected resources in the target domain with respect to authorization decisions, and
- a protected resource in the target domain cannot verify an access token issued by an authorization server in another trust domain.
Therefore, token exchange in these cases must use an intermediate proof issued by the authorization server in the originating domain and trusted by the authorization server in the target domain. This proof is represented as a signed JWT in which the authorization server in the originating domain asserts relevant claims about the sending client and authenticated user.
For this to function, a trust relationship must be configured between the authorization servers in the two domains; see Section 3.2.1 below.
sequenceDiagram
autonumber
box Domain A
actor User as User
participant Service as Application<br/>(Client)
participant AsA as Authorization Server A
participant ApiA as Protected Resource<br/>API A
end
box Domain B
participant AsB as Authorization Server B
participant ApiB as Protected Resource<br/>API B
end
User-->Service: Logged in
User-->AsA: Has session at Authorization Server
User-->>Service: Action ...
Service->>+AsA: Token Exchange Request (RFC8693)
AsA->>-Service: Authorization Grant JWT (RFC7523)
Service->>+AsB: Access Token Request<br />Pass Authorization Grant JWT (RFC7523)
AsB->>-Service: Access Token Response
Service->>+ApiB: Make API call<br />Include Access Token
ApiB->>-Service: API response
Service-->>User: Response ...
The sequence diagram above describes a token exchange operation that enables an application in domain A to invoke a protected resource in domain B.
-
The user is assumed to be logged in to the application in domain A. How this login was performed is out of scope for this profile.
-
For this illustration, it is assumed that the end-user has a relationship with the authorization server; that is, at some point the user was directed to the authorization server, where the user was authenticated and access rights to a protected resource were authorized.
-
The user performs an action in the application that requires the application to access a resource in domain B.
-
To obtain a signed attestation from the authorization server in domain A, which can then be used to request an access token for domain B, the application makes an OAuth 2.0 token exchange request to the authorization server. Included in this request is a previously acquired access or refresh token. See Section 3.3.1 and Section 3.3.2.
-
Based on its configuration and established trust relationships, the authorization server in domain A returns a signed JWT. This JWT contains claims attesting to the information needed by the authorization server in domain B to issue an access token. See Section 3.3.4.
-
The application (client) in domain A then uses the received JWT authorization grant in a token request to the authorization server in domain B. This is done according to the authorization grant processing requirements defined in [RFC7523]. See Section 3.4.1.
-
The authorization server in domain B processes the request according to Section 3.4.2 and issues an access token that can be used to access the protected resource in domain B. See Section 3.4.3.
Steps 8–10 follow normal OAuth 2.0 access token usage: the client provides the access token in the request to the protected resource, which validates it before granting access and returning a response.
The cross-domain use case can also be combined with the previous use case, where a protected resource in domain A acts as an OAuth 2.0 client towards domain B. This is illustrated in the sequence diagram below. The requirements in the following sections also cover these usages of token exchange.
sequenceDiagram
box Domain A
actor User as User
participant Service as Application<br/>(Client)
participant AsA as Authorization Server A
participant ApiA as Protected Resource<br/>API A
end
box Domain B
participant AsB as Authorization Server B
participant ApiB as Protected Resource<br/>API B
end
User-->>Service: Action ...
Service-->>+User: Redirect
User->>-AsA: Authorization Request
User-->AsA: Authenticate (and possibly consent)
AsA-->>+User: Redirect
User->>-Service: Authorization Response w. code
Service->>+AsA: Token Request w. code
AsA->>-Service: Token Response w. Access Token
Service->>+ApiA: Make API call<br/>Include Access Token
ApiA->>+AsA: Token Exchange Request (RFC8693)
AsA->>-ApiA: Authorization Grant JWT (RFC7523)
ApiA->>+AsB: Access Token Request<br/>Pass Authorization Grant JWT (RFC7523)
AsB->>-ApiA: Access Token Response
ApiA->>+ApiB: Make API call<br/>Include Access Token
ApiB->>-ApiA: API response
ApiA->>-Service: API response
Service-->>User: Response ...
3.2.1. Domain Trust Relationships and Prerequisites
For the above token exchange flows to be possible, there must be a trust relationship configured in which the authorization server in the target domain accepts authorization grant JWTs issued by the authorization server in the originating domain. In addition, all entities in the originating domain that make cross-domain calls must be registered as OAuth 2.0 clients at the authorization server in the target domain.
How these relationships are established, and the requirements for trust, are out of scope for this specification.
However, the minimum requirements for establishing the cross-domain use case are as follows:
-
The authorization server in the originating domain MUST support OAuth 2.0 Token Exchange as defined in [RFC8693] and as profiled by this specification.
-
The authorization server in the target domain MUST support JWT authorization grants as defined in [RFC7523] and as profiled by this specification.
-
The key used by the authorization server in the originating domain MUST be known to the authorization server in the target domain.
-
The issuer identifier of the authorization server in the originating domain MUST be known to the authorization server in the target domain and associated with the correct key and configuration.
-
The issuer identifier of the authorization server in the target domain MUST be known to the authorization server in the originating domain and linked to the token exchange configuration for the target domain.
-
All entities in the originating domain that may act as clients towards the target domain MUST be registered at the authorization server in the target domain.
-
How this registration is performed is out of scope for this specification. It may be done out of band via manual procedures, or through automatic client registration using OpenID Federation.
-
An OAuth 2.0 entity in the originating domain MAY be named or identified differently in the target domain. In such cases, the authorization server in the originating domain MUST be aware of both identities when issuing the authorization grant JWT.
-
Also, there is no guarantee that the scopes used in the target domain have any meaning in the originating domain. Therefore, the authorization servers may need to maintain mappings of scopes and other rights, and define how to apply these control mechanisms when managing authorization across domain boundaries. See Section 3.5.1 below.
3.3. Token Exchange
Token exchange across domains differs from the intra-domain case in Section 2: the output is not an access token for the target protected resource, but an authorization grant in the form of a signed JWT that the client presents to the authorization server in the target domain to obtain an access token. The authorization server in the originating domain acts as an STS as per [RFC8693] and issues a JWT authorization grant suitable for use with the JWT bearer authorization grant defined in [RFC7523].
Under this profile, the authorization server in the originating domain MUST issue a short-lived, one-time-use JWT that attests to the delegating user and the requesting client, and that is explicitly targeted at the authorization server in the target domain.
3.3.1. Token Exchange Request
A client in the originating domain (or a protected resource acting as a client) MUST call the originating authorization server’s token endpoint with a token exchange request conformant to [RFC8693] with the following profile requirements:
-
The request MUST include:
-
grant_type
with a value ofurn:ietf:params:oauth:grant-type:token-exchange
. -
subject_token
containing an inbound token issued by the originating authorization server (see Section 3.3.2). -
subject_token_type
indicating the type ofsubject_token
:urn:ietf:params:oauth:token-type:access_token
for an access token, orurn:ietf:params:oauth:token-type:refresh_token
for a refresh token.
-
A target authorization server indicator identifying the authorization server in the target domain. The client MUST supply one of
audience
andresource
. See Section 4.1 for further requirements.
-
-
The client SHOULD include
requested_token_type
with a value ofurn:ietf:params:oauth:token-type:jwt
to explicitly request a JWT authorization grant as defined in [RFC7523].- See also the requirements about "Servers supporting both use cases" in Section 3.3.3.
-
The client MAY use the
scope
parameter to specify particular scope(s) for the request.-
In deployments where the subject (user) is the actual resource owner, the client MUST NOT request a scope that is not authorized by the user in relation to the presented
subject_token
. See Section 4.3. -
If the originating and target domains use different scope models, whether the supplied scope values are specific for the originating or target domain is deployment specific. See Section 3.5.1.
-
Client authentication at the token endpoint MUST follow [Ena.OAuth2.Profile]. If private_key_jwt
is used, the iss
and sub
of the client assertion MUST equal the client’s identifier registered at the originating authorization server.
3.3.2. Inbound Token Requirements
This profile defines the following requirements for the subject_token
used as input to the token exchange:
-
The
subject_token
MUST be either an access token or a refresh token issued by the originating authorization server to the requesting client. -
The token MUST be valid, not expired, and not revoked at the time of the request.
-
The token MUST be bound to a user.
A requesting entity MUST NOT include a token that does not fulfil all the above requirements in a token exchange request.
3.3.3. Processing Requirements
When the originating authorization server receives a conformant token exchange request, it MUST:
-
Validate the
subject_token
according to Section 4.2.2, Processing Requirements for a Subject Token. -
Verify that the
subject_token
is user-bound. If not, the request MUST be rejected withinvalid_request
. -
Authenticate the client and verify it is authorized to request cross-domain token exchange for the indicated target authorization server.
-
Verify that the target authorization server indicated by
audience
/resource
is configured as a trusted peer and that key material and issuer identifiers are established as per Section 3.2.1. If not, the request MUST be rejected withinvalid_target
orunauthorized_client
. -
Assert that
requested_token_type
isurn:ietf:params:oauth:token-type:jwt
, or if it is omitted, apply the logic from "Servers supporting both use cases" below.
If the request is invalid, the server MUST respond with an error per [RFC8693]. Where applicable, the following errors SHOULD be used: invalid_request
, invalid_scope
, unauthorized_client
, invalid_target
, and server_error
.
Servers supporting both use cases: An authorization server that supports both the intra-domain exchange in Section 2 and the cross-domain exchange in this section MUST use the requested_token_type
parameter to disambiguate the requested behaviour:
If requested_token_type
is set to urn:ietf:params:oauth:token-type:access_token
, the server MUST process the request under the rules of Section 2, and if requested_token_type
is set to urn:ietf:params:oauth:token-type:jwt
, the server MUST process the request under the rules of this section.
Clients SHOULD always supply requested_token_type
. If requested_token_type
is omitted, the server MAY infer intent from the target indicator, where the cross-domain case will be chosen if the target identifies an authorization server, and the intra-domain case will be chosen if the target identifies a protected resource within the same domain.
If the intent cannot be determined unambiguously, the server MUST reject the request with invalid_request
.
3.3.4. Token Exchange Response and JWT Contents
The token exchange response MUST be a JSON object as defined by [RFC8693] with these profile requirements:
-
The JWT authorization grant MUST be returned in the
access_token
member. -
issued_token_type
MUST beurn:ietf:params:oauth:token-type:jwt
. -
token_type
MUST be included and set toN_A
. The JWT authorization grant is not a bearer token usable at a resource server. -
expires_in
SHOULD be included and reflect the remaining lifetime of the JWT authorization grant. -
The
scope
parameter MUST be provided if the scopes included in the issued JWT differ from those requested by the client; otherwise, the parameter is OPTIONAL.
The JWT returned in access_token
MUST comply with Section 3 of [RFC7523] and this profile.
-
iss
MUST be the issuer identifier of the originating authorization server. -
sub
MUST be the end-user identifier, chained from the inbound token, or a transcription of the identity according to Section 3.5.2. -
aud
MUST be set to the issuer identifier of the target authorization server.- An additional audience value containing the token endpoint URL of the target authorization server MAY be included to accommodate different interpretations of how audience values are handled.
-
jti
MUST be present and unique for each issuance. -
exp
MUST be included. Theiat
andnbf
claims SHOULD also be included to support replay protection and precise validity handling. The validity period MUST be short. As an example, deployments often use no more than 5 minutes. -
client_id
MUST identify the requesting client as registered at the target authorization server.- If the client has a different identifier in the originating domain, that identifier SHOULD appear as the first-level
sub
insideact
, preserving traceability without affecting authorization.
- If the client has a different identifier in the originating domain, that identifier SHOULD appear as the first-level
-
act
SHOULD be included to represent the chain of actors as defined in [RFC8693]. The first-levelsub
underact
SHOULD identify the client as known in the originating domain. Additional nested actors from earlier hops SHOULD also be preserved.- The contents of
act
MUST NOT be used for authorization decisions. It is only for accountability and traceability.
- The contents of
-
Authentication context. If present in the inbound token,
acr
,amr
,auth_time
and similar claims MUST be copied into the JWT authorization grant. -
If scope information needs to be provided, for example, if the originating subject token contains scopes or if scopes are included in the token exchange request, the
scope
claim SHOULD be included and contain the scopes that the calling entity is authorized for.- If the originating and target domains use different scope models, whether the scope values included are specific to the originating or target domain is deployment specific. See Section 3.5.1.
-
Additional claims MAY be included based on local policies or bilateral agreements between the originating and target domains.
The JWT authorization grant MUST be signed by the originating authorization server using a key that the target authorization server has associated with the originating issuer (Section 3.2.1). The JWT authorization grant MAY be encrypted if both domains have explicitly configured encryption keys and policies.
3.4. Authorization Grant Requirements
This section profiles how the client uses the JWT authorization grant at the target authorization server, and how the target authorization server processes it and issues an access token.
3.4.1. Access Token Request According to RFC7523
The HTTP request to the target authorization server’s token endpoint MUST follow Section 2.1 of [RFC7523] with the following clarifications and additions.
-
The client MUST present the JWT authorization grant to the token endpoint of the target authorization server using the JWT bearer grant defined in [RFC7523].
-
grant_type
is set tourn:ietf:params:oauth:grant-type:jwt-bearer
. -
assertion
is set to the JWT authorization grant produced according to the requirements stated in Section 3.3.4.
-
-
The client MUST authenticate to the target token endpoint according to [Ena.OAuth2.Profile]. If
private_key_jwt
is used, theiss
andsub
of the client assertion MUST equal the client’s identifier as registered at the target authorization server. This identifier MAY differ from the identifier used in the originating domain. -
The client MAY include
scope
to request specific scopes in the target domain. -
The client MAY include a
resource
parameter to indicate the intended protected resource in the target domain, if the target authorization server supports [RFC8707]. If used, the requirements in Section 7.1 of [Ena.OAuth2.Profile] MUST be followed.- The
audience
parameter MUST NOT be used in JWT bearer grant requests (it is a special-purpose parameter for OAuth 2.0 Token Exchange).
- The
3.4.2. Processing of JWT Authorization Grant
When the target authorization server receives a JWT bearer grant request as described in Section 3.4.1, it MUST process the request as follows:
-
Client authentication – The client MUST be authenticated in accordance with Section 8.3 of [Ena.OAuth2.Profile].
-
Assertion validation – The server MUST validate the JWT assertion in accordance with [RFC7523]. This includes verifying the digital signature, issuer, subject, audience,
jti
(for replay protection), and theiat
,nbf
, andexp
claims. The issuer MUST correspond to a trusted originating authorization server, and the signing key MUST be bound to that issuer as described in Section 3.2.1. Theaud
claim of the JWT MUST contain the issuer identifier for the target authorization server. -
Scope and resource determination – The server MUST determine the scopes and target resources for the token to be issued. This decision MUST take into account any
resource
andscope
parameters in the request, values carried in the assertion, and locally configured scope or resource mappings as described in Section 3.5.1. -
Subject determination – The server MUST determine the end-user identifier to be carried forward from the assertion for identity chaining. If needed, user identity transcription MAY be applied as described in Section 3.5.2.
-
Client identity determination – The server MUST determine the client identifier as registered in the target domain for the requesting entity.
-
Actor chain handling – If the assertion contains an
act
claim, all actor values from the assertion MUST be preserved. The target authorization server MAY add an additional actor to reflect the registered client in the target domain. Theact
claim MUST NOT be used for authorization decisions. -
Policy enforcement – The server MUST enforce local policy, including user consent, scope minimisation, and resource restrictions. If requested scopes cannot be satisfied, the request MUST be rejected with the
invalid_scope
error. -
Issuance decision – After successful processing, the server MUST issue an access token and return a response as defined in Section 3.4.3.
If any of the above checks fail, the authorization server MUST reject the request and return an error response in accordance with [RFC7523] and [RFC6749].
3.4.3. Token Response
The access token response MUST follow [RFC6749] and [Ena.OAuth2.Profile]. The access token issued by the target authorization server MUST follow the requirements stated in Section 6.1 of [Ena.OAuth2.Profile], with the following additions and clarifications:
-
If the JWT authorization grant contained an
act
claim, this claim MAY be included in the resulting access token. If so, all actor values MUST be preserved in the issued access token. The target authorization server MAY add an additional actor to represent the registered client in the target domain. -
Proof-of-possession policies in the target domain MUST be observed. If DPoP per [RFC9449] is required, the access token MUST be bound accordingly and MUST NOT be issued as a simple bearer token.
Furthermore, the token response MUST NOT include a refresh token unless explicitly permitted by target-domain policy. If a refresh token is issued, its use MUST remain confined to the target domain.
3.5. Additional Features and Advanced Topics
3.5.1. Scope Mapping Across Domains
Scope values used within a domain may be specific to that domain and have no meaning outside it. This must be considered in the cross-domain token exchange case, where the authorization server in the originating domain issues the JWT containing the identity of the user along with the client authorizations (scopes), for the authorization server in the target domain to consume.
This profile does not specify how such scope mapping should be performed, other than that deployments MUST define a deterministic mapping from originating-domain entitlements to target-domain scopes. Whether this mapping is maintained in the originating or target domain is deployment specific.
An alternative to domain-specific scopes with mappings handled by an authorization server is an approach where the originating domain incorporates relevant scopes from the target domain into its own security and authorization model, and clients within the originating domain request those scopes directly.
3.5.2. Transcription of User Identity Claims
Subject identifiers or other relevant user identity claims may differ between domains. For example, a user may be identified differently in the originating domain than in the target domain. In such cases, either the authorization server in the originating domain or the authorization server in the target domain may perform a transcription between identities. Which server performs this depends on which party has knowledge of the required mappings.
In cross-domain use cases, it may also be necessary to prevent the disclosure of a user’s actual identity in the target domain. In such cases, it may be sufficient for the protected resource to know only that the user originates from the originating domain. The authorization server in the originating domain is responsible for replacing the actual user identity (for example, the sub
claim) with a pseudonymous value. If this feature is used, the originating authorization server MUST be able to map the pseudonym back to the actual identity value, for example for out-of-band investigations of potential attacks or fraud.
3.6. Examples
This section provides a non-normative, end-to-end illustration of the cross-domain token exchange flow as described in the first sequence diagram in Section 3.2.
The example uses the following identifiers:
- Authorization server in domain A (originating domain):
https://as.domain-a.com
- Application (client) in domain A:
https://app.domain-a.com
- Protected resource in domain A:
https://api.domain-a.com
- Authorization server in domain B (target domain):
https://as.domain-b.com
- Protected resource in domain B:
https://api.domain-b.com
- User identity (subject):
user-1234
For readability, long values are folded and signatures are abbreviated.
Note on scopes across domains: In this example, the originating domain uses the scope a-api-read
and the target domain uses the scope b-api-read
. This reflects that scopes are domain-specific and require mapping as described in Section 3.5.1.
Furthermore, for this example, the meaning of a-api-read
is that the possession of it grants access to API A and API B (and possibly other API:s in B). In domain B, the scope b-api-read
grants access to API B.
Inbound Access Token:
The decoded access token JWT that the application in domain A has in its possession is shown below.
{
"iss": "https://as.domain-a.com",
"aud": ["https://api.domain-a.com", "https://as.domain-a.com"],
"sub": "user-1234",
"acr": "http://id.elegnamnden.se/loa/1.0/loa3",
"client_id": "https://app.domain-a.com",
"scope": "a-api-read a-api-write",
"jti": "inbound-app-123",
"nbf": 1696500000,
"iat": 1696500000,
"exp": 1696503600
}
As shown in the JWT, the access token was issued for use at https://api.domain-a.com
(a protected resource within domain A). The authorization server has also added itself as a valid audience (https://as.domain-a.com
). See Section 4.2.1, Issuing a Token Usable for Token Exchange.
In this example, the acr
claim is included to indicate the authentication context under which the subject (user) was authenticated. In a real-life scenario, the access token may contain additional claims representing the user identity and authentication.
It is worth noting that the access token contains two scopes: a-api-read
and a-api-write
.
Token Exchange Request:
Next, the application needs to make a cross-domain call to domain B, and therefore submits a token exchange request according to Section 3.3.1 to the authorization server in its own domain.
POST /token HTTP/1.1
Host: as.domain-a.com
Content-Type: application/x-www-form-urlencoded
grant_type=urn:ietf:params:oauth:grant-type:token-exchange&
subject_token=eyJhbGciOi...inbound-app-123...&
subject_token_type=urn:ietf:params:oauth:token-type:access_token&
audience=https%3A%2F%2Fas.domain-b.com&
scope=a-api-read&
client_id=https%3A%2F%2Fapp.domain-a.com&
client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&
client_assertion=eyJhbGciOi...
-
The
subject_token
provided is the inbound access token shown above. -
The
audience
parameter is set to the issuer identifier of the authorization server in domain B. -
The
scope
is set toa-api-read
. This indicates that the application is instructing the authorization server not to include thea-api-write
scope from the inbound access token in the resulting JWT. This filtering could also be performed by the authorization server before issuing the JWT. -
The
client_assertion
contains theprivate_key_jwt
assertion that the application uses to authenticate the call.
Token Exchange Response with JWT Authorization Grant:
The authorization server in domain A processes the token exchange request according to Section 3.3.3 and, if permitted by the token exchange policy for domain B, issues a JWT authorization grant as specified in Section 3.3.4.
The response:
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
{
"access_token": "eyJhbGciOi...jwt-authorization-grant...",
"issued_token_type": "urn:ietf:params:oauth:token-type:jwt",
"token_type": "N_A",
"expires_in": 300,
"scope": "a-api-read"
}
The decoded JWT authorization grant (the value of the response access_token
field):
{
"iss": "https://as.domain-a.com",
"aud": "https://as.domain-b.com",
"sub": "user-1234",
"acr": "http://id.elegnamnden.se/loa/1.0/loa3",
"client_id": "https://app.domain-a.com",
"scope": "a-api-read",
"jti": "grant-456",
"nbf": 1696500000,
"iat": 1696500000,
"exp": 1696500300,
"act": {
"sub": "https://app.domain-a.com"
}
}
-
The
sub
andacr
claims from the initial access token are included in the JWT. Additional claims regarding the user authentication process and user identity may be included in real-life scenarios.- Note that the
sub
value is unchanged from the inbound access token. This means that no transcription of user identity claims, as described in Section 3.5.2, was performed.
- Note that the
-
The
scope
claim contains the valuea-api-read
. This means that no scope mapping, as described in Section 3.5.1, was performed by authorization server A. In this case, authorization server B must maintain a scope mapping to translatea-api-read
into a scope value meaningful in domain B.- Note: It is also possible for the authorization server in domain B to perform this mapping. Which domain carries out scope mappings is deployment-specific.
-
The
scope
claim does not include thea-api-write
value that was present in the inbound access token. In this example, the application (client) requested only thea-api-read
scope in the token exchange request. Other reasons why a claim might be removed from the original authorization include that the client is not entitled to use it in cross-domain scenarios, or that the claim has no mapping in the target domain. -
No
resource
parameter is included, since the corresponding token exchange request did not specify any protected resource in domain B.
Access Token Request to Authorization Server in Domain B:
Next, the application in domain A acts as an OAuth 2.0 client towards the authorization server in domain A, and sends a token request according to Section 3.4.1, including the JWT authorization grant.
POST /token HTTP/1.1
Host: as.domain-b.com
Content-Type: application/x-www-form-urlencoded
grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&
assertion=eyJhbGciOi...grant-456...&
scope=b-api-read&
client_id=https%3A%2F%2Fapp.domain-a.com&
resource=https%3A%2F%2Fapi.domain-b.com&
client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&
client_assertion=eyJhbGciOi...
-
The domain A application (client) requests the scope
b-api-read
, which is a scope value specific to domain B. Whether the client is authorized to request this scope is determined by the authorization server in domain B, based on translating the domain A–specific scopes received in the JWT authorization grant and applying the token exchange policies configured for domain A. -
The domain A application (client) specifies the intended protected resource by supplying its identifier in the
resource
parameter.
Access Token Response from Authorization Server in Domain B:
When the authorization server in domain B receives the token request, it processes it according to Section 3.4.2 before issuing a token response containing an access token, as specified in Section 3.4.3.
The token response:
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
{
"access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6ImJiLWtpZC0wMDEiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL2FzLmRvbWFpbi1iLmNvbSIsImF1ZCI6Imh0dHBzOi8vYXBpLmRvbWFpbi1iLmNvbSIsInN1YiI6InVzZXItMTIzNCIsImNsaWVudF9pZCI6Imh0dHBzOi8vYXBwLmRvbWFpbi1hLmNvbSIsInNjb3BlIjoiYi1hcGktcmVhZCIsImp0aSI6Im5ldy1iLTc4OSIsIm5iZiI6MTY5NjUwMDMwMCwiaWF0IjoxNjk2NTAwMzAwLCJleHAiOjE2OTY1MDM5MDB9.au3P...sig",
"issued_token_type": "urn:ietf:params:oauth:token-type:access_token",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "b-api-read"
}
The decoded access token:
{
"iss": "https://as.domain-b.com",
"aud": "https://api.domain-b.com",
"sub": "user-1234",
"client_id": "https://app.domain-a.com",
"https://claim.domainb.com/custom": "foobar",
"scope": "b-api-read",
"act": {
"sub": "https://app.domain-a.com"
},
"jti": "new-b-789",
"nbf": 1696500300,
"iat": 1696500300,
"exp": 1696503900
}
-
In the access token above, the
acr
claim is not included. For this example, we assume that this information was only relevant to the authorization server in domain B in order to permit the token exchange. -
To illustrate how the authorization server that approved the JWT authorization request may add claims specific to its domain resources, the claim
https://claim.domainb.com/custom
is included.
Given this access token, the application in domain A can now call the protected resource https://api.domain-b.com
in domain B.
4. General Token Exchange Requirements and Considerations
This section defines requirements and considerations that are common to both use cases profiled in this specification.
4.1. The Resource and Audience Parameters
The resource
parameter, as defined in [RFC8707], and the audience
parameter, as defined in [RFC8693], are two separate but related ways of indicating the target service for a token exchange operation.
[RFC8693] states that the resource
parameter should be used when the client does not know the logical name of the target service, and that the audience
parameter should be used when such a logical name is known to the client.
To promote interoperability, this profile specifies the following requirements:
-
If the
resource
parameter is used, the requirements from Section 7.1 of [Ena.OAuth2.Profile] MUST be followed. -
If the
audience
parameter is used to indicate a protected resource, the Resource Identifier of the resource as defined in Section 4.3 of [Ena.OAuth2.Profile] MUST be used. -
If the
audience
parameter is used to indicate an authorization server (as in the use case defined in Section 3), the issuer identifier of the authorization server MUST be used. -
An entity compliant with this profile MUST NOT use both the
resource
andaudience
parameters in the same request. -
If a token exchange request includes a
scope
value from which the authorization server can deduce the target service, both theresource
andaudience
parameters MAY be omitted.
4.2. Subject Token Requirements and Considerations
The token supplied as a subject_token
in a token exchange request, for the use cases profiled in this specification, is either an access token or a refresh token.
This section defines the requirements for issuing access tokens and refresh tokens that may later be used in a token exchange request, as well as the requirements that an authorization server functioning as a Security Token Service MUST apply when processing such a request.
4.2.1. Issuing a Token Usable for Token Exchange
This section specifies requirements and considerations for authorization servers that issue tokens which may later be used as input in a token exchange request to the same authorization server.
-
An authorization server issuing an access token intended for later use in a token exchange request SHOULD add its own issuer identifier among the audience (
aud
) values of the access token.- If the sole purpose of the access token is to be used in a token exchange, for example in cross-domain scenarios, the authorization server’s issuer identifier MUST be included in the
aud
claim as the only value.
- If the sole purpose of the access token is to be used in a token exchange, for example in cross-domain scenarios, the authorization server’s issuer identifier MUST be included in the
-
An authorization server issuing an access token for later use in a token exchange request MAY include the
may_act
claim, as defined in Section 4.4 of [RFC8693], where this claim contains asub
claim equal to the client requesting the access token (client_id
). -
For the access token requirements above, the following MUST hold: If a refresh token is issued together with an access token, the representation of the access token MUST also be valid for the corresponding refresh token.
Example:
{
"aud": ["https://api.example.com", "https://as.example.com"],
"iss": "https://as.example.com",
"sub": "user-1234",
"client_id": "https://client.example.com",
"may_act": {
"sub": "https://client.example.com"
},
"scope": "api-read",
"jti": "8ujkdsna7",
"nbf": 1696500000,
"iat": 1696500000,
"exp": 1696503600
}
4.2.2. Processing Requirements for a Subject Token
This section specifies the requirements for how an authorization server processing a token exchange request MUST verify the subject token (subject_token
) provided in the request.
-
An access token that is not signed in accordance with the requirements in Section 6.1 of [Ena.OAuth2.Profile] MUST be rejected.
-
An access token that was not issued by the processing authorization server MUST be rejected.
-
The authorization server MUST verify that the token (access or refresh) has not expired.
-
The authorization server MUST verify that the token has not been revoked or otherwise invalidated.
-
The token MUST contain a
client_id
claim whose value matches the requesting entity's client identifier. If not, the request MUST be rejected. -
An access token obtained through the client credentials grant, or any other grant that does not involve a user, MUST be rejected. Such tokens lack user identity and therefore cannot support identity chaining.
-
If the authorization server issues tokens with its own issuer identifier among the audience values (see Section 4.2.1), the token MUST be rejected if that issuer identifier does not appear in the
aud
claim. -
If the authorization server issues tokens with a
may_act
claim (see Section 4.2.1), thesub
claim insidemay_act
MUST equal the requesting entity's client identifier. Otherwise, the request MUST be rejected.
Note: When a refresh token is supplied as a subject_token
, its underlying representation, based on the original authorization, is verified against the requirements above.
4.3. Token Exchange and the User and Resource Owner Distinction
Section 1.5 of [Ena.OAuth2.Profile] describes the distinction between the typical OAuth 2.0 usage, where the user is the resource owner and delegates access to a client for a protected resource, and cases where the OAuth authorization code flow is used even though the user is not the owner of the protected resource.
The major difference between these two OAuth usages lies in what happens at the authorization server when a client sends an authorization request:
-
In deployments where the user is the actual resource owner, the authorization server first authenticates the user and then asks for the user’s consent* to grant the requesting client access to the protected resource (owned by the user). Scopes are often used to represent the type of access that is requested and granted.
In this case, the resulting access token represents the rights that the user has delegated to the client for a particular resource. -
In deployments where the user is not the resource owner, the authorization server also authenticates the user, but then performs an authorization process to determine whether the user should be allowed to use the client to access the protected resource. Scopes may also be used to represent the type of access that is requested and granted.
In this case, the resulting access token represents the rights that the authorization server has granted to the user for using the client to access a particular protected resource.
Given these distinctions, this profile defines the following requirements for token exchange requests:
-
In deployments where the user is the actual resource owner:
- The authorization server MUST NOT issue access tokens or authorization grant JWTs containing scope values that are not represented in the supplied subject token, and therefore not authorized by the resource owner.
-
In deployments where the user is not the resource owner:
- The authorization server MAY issue access tokens or authorization grant JWTs containing additional scope values (that is, other than those represented in the provided subject token), provided that the user and requesting client are authorized for these scopes. This is permitted because, in these use cases, there is no initial user consent to consider.
[*]: User consent may be either explicit, meaning that the user gives consent through a dialogue at the authorization server, or implicit, meaning that the consent is based on a previously accepted user agreement or similar.
5. References
5.1. Normative References
Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", March 1997.
Hardt, D., "The OAuth 2.0 Authorization Framework", RFC 6749, DOI 10.17487/RFC6749, October 2012.