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

# RFC 8693 OAuth 2.0 Token Exchange

> Explanation about the "RFC 8693 OAuth 2.0 Token Exchange" specification and Authlete's implementation.

<Note>
  This page is for Authlete 3.0. For 2.x, see [this page](/v2/protocols-and-flows/grant-types/token-exchange).
</Note>

# Introduction

[RFC 8693 OAuth 2.0 Token Exchange](https://www.rfc-editor.org/rfc/rfc8693.html) (hereinafter "Token Exchange") is a technical standard that defines a way to get a new token by presenting an existing token and optionally one more existing token at the token endpoint.

The specification is very flexible. To put it the other way around, the specification does not define details that are necessary for secure token exchange. Therefore, you have to consider further details in the undefined part to implement the specification in an authorization server.

This article describes some key details to implement the Token Exchange specification and Authlete's support of this specification.

## Specification

The diagram below illustrates the token exchange flow.

<img src="https://mintcdn.com/authlete/oZd1VUaYFwHO2MBx/protocols-and-flows/advanced-flows/token_exchange.png?fit=max&auto=format&n=oZd1VUaYFwHO2MBx&q=85&s=c207d63fc59bd98e2cbcba97a691db2b" alt="Token Exchange" width="3153" height="1805" data-path="protocols-and-flows/advanced-flows/token_exchange.png" />

The following sections explain token types and token exchange request/response.

### Tokens

There are two kinds of input tokens; a subject token and an actor token.

### Subject Token

"Subject Token" is a mandatory input token. It *"represents the identity of the party on behalf of whom the request is being made."* (excerpt from [Section 2.1. Request](https://www.rfc-editor.org/rfc/rfc8693.html#section-2.1) of [RFC 8693](https://www.rfc-editor.org/rfc/rfc8693.html))

The specification expects that the subject identified by the subject token is used as the subject of the newly issued token.

### Actor Token

"Actor Token" is an optional input token. It *"represents the identity of the acting party."* (excerpt from [Section 2.1. Request](https://www.rfc-editor.org/rfc/rfc8693.html#section-2.1) of [RFC 8693](https://www.rfc-editor.org/rfc/rfc8693.html))

If there is a need to distinguish the subject of the newly issued token from the acting party that uses the token, authorization server implementations may utilize the actor token and embed information about the acting party in the token to issue. [Section 4.1](https://www.rfc-editor.org/rfc/rfc8693.html#section-4.1) and [Section 4.4](https://www.rfc-editor.org/rfc/rfc8693.html#section-4.4) of [RFC 8693](https://www.rfc-editor.org/rfc/rfc8693.html) define JWT claims related to the acting party.

### Token Types

As possible types of the tokens above, the specification lists the following **token types** and assigns token type identifiers to them. The identifiers of token types are registered at [OAuth URI](https://www.iana.org/assignments/oauth-parameters/oauth-parameters.xhtml#uri) of [OAuth Parameters](https://www.iana.org/assignments/oauth-parameters/oauth-parameters.xhtml) of IANA (Internet Assigned Numbers Authority).

| Token Type         | Token Type Identifier                            |
| :----------------- | :----------------------------------------------- |
| JWT                | `urn:ietf:params:oauth:token-type:jwt`           |
| Access Token       | `urn:ietf:params:oauth:token-type:access_token`  |
| Refresh Token      | `urn:ietf:params:oauth:token-type:refresh_token` |
| ID Token           | `urn:ietf:params:oauth:token-type:id_token`      |
| SAML 1.1 Assertion | `urn:ietf:params:oauth:token-type:saml1`         |
| SAML 2.0 Assertion | `urn:ietf:params:oauth:token-type:saml2`         |

<Note>
  The token type identifier for JWT is defined in [RFC 7519 JSON Web Token (JWT)](https://www.rfc-editor.org/rfc/rfc7519.html). Others are defined in [RFC 8693 OAuth 2.0 Token Exchange](https://www.rfc-editor.org/rfc/rfc8693.html).
</Note>

### Token Exchange Request

A **token exchange request** is a kind of token requests.

### Grant Type

To distinguish token exchange requests from other token requests, a new grant type `urn:ietf:params:oauth:grant-type:token-exchange` is defined in the specification. The value is used as the value of the `grant_type` request parameter of a token request.

### Client Identification and Authentication

The specification does not require **[client authentication](https://darutk.medium.com/oauth-2-0-client-authentication-4b5f929305d4)** and even **client identification** at the token endpoint. [Section 2.1. Request](https://www.rfc-editor.org/rfc/rfc8693.html#section-2.1) of [RFC 8693](https://www.rfc-editor.org/rfc/rfc8693.html) states it as follows.

> The supported methods of client authentication and whether or not to allow **unauthenticated** or **unidentified** clients are deployment decisions that are at the discretion of the authorization server.

Technically speaking, "unauthenticated clients" means public clients (cf. [RFC 6749](https://www.rfc-editor.org/rfc/rfc6749.html) [Section 2.1. Client Types](https://www.rfc-editor.org/rfc/rfc6749.html#section-2.1)) and "unidentified clients" means that a token request does not contain information whereby to identify the client making the request.

Although [Appendix 1.1](https://www.rfc-editor.org/rfc/rfc8693.html#section-a.1.1) of [RFC 8693](https://www.rfc-editor.org/rfc/rfc8693.html) shows an example of token exchange request from an unidentified client, such cases are appropriate only in limited conditions, such as a closed network within a service. In other circumstances, you have to define further details, which are out of the scope of [RFC 8693](https://www.rfc-editor.org/rfc/rfc8693.html), for secure token exchange.

### Request Parameters

The following table shows parameters related to token exchange requests.

| Request Parameter      | Necessity | Description                                                                                                                                                                                                                                                                                 |
| :--------------------- | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `grant_type`           | REQUIRED  | The value `urn:ietf:params:oauth:grant-type:token-exchange` indicates that the token request is a token exchange request.                                                                                                                                                                   |
| `resource`             | OPTIONAL  | Resources to be tied to the newly issued token. This request parameter may be specified multiple times. See [RFC 8707 Resource Indicators for OAuth 2.0](https://www.rfc-editor.org/rfc/rfc8707.html) for details.                                                                          |
| `audience`             | OPTIONAL  | Audience of the newly issued token. This request parameter also may be specified multiple times.                                                                                                                                                                                            |
| `scope`                | OPTIONAL  | A list of space-delimited names of scopes that are to be tied to the newly issued token.                                                                                                                                                                                                    |
| `requested_token_type` | OPTIONAL  | The token type of the newly issued token that the client wishes. One of the registered token type identifiers.                                                                                                                                                                              |
| `subject_token`        | REQUIRED  | The value of the subject token.                                                                                                                                                                                                                                                             |
| `subject_token_type`   | REQUIRED  | The token type of the subject token. One of the registered token type identifiers.                                                                                                                                                                                                          |
| `actor_token`          | OPTIONAL  | The value of the actor token.                                                                                                                                                                                                                                                               |
| `actor_token_type`     | OPTIONAL  | The token type of the actor token. One of the registered token type identifiers. When the `actor_token` request parameter is given, this request parameter is REQUIRED. On the contrary, when the `actor_token` request parameter is not given, this request parameter must not be present. |

<Note>
  [RFC 6749 The OAuth 2.0 Authorization Framework](https://www.rfc-editor.org/rfc/rfc6749.html) states *"Request and response parameters MUST NOT be included more than once."* The `resource` request parameter and `audience` request parameter are exceptions.
</Note>

### Token Exchange Response

A **token exchange response** is a kind of token responses.

### Response Parameters

The following table shows parameters related to token exchange responses.

| Response Parameter  | Necessity | Description                                                                                                                                                                                                                                                                                 |
| :------------------ | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `access_token`      | REQUIRED  | Regardless of the token type, the value of the newly issued token is set to this response parameter.                                                                                                                                                                                        |
| `issued_token_type` | REQUIRED  | The token type of the newly issued token. One of the registered token type identifier.                                                                                                                                                                                                      |
| `token_type`        | REQUIRED  | When the token type of the newly issued token is `urn:ietf:params:oauth:token-type:access_token`, this response parameter has the same meaning as defined in [RFC 6749 The OAuth 2.0 Authorization Framework](https://www.rfc-editor.org/rfc/rfc6749.html). In other cases, `"N_A"` is set. |
| `expires_in`        | OPTIONAL  | The lifetime of the newly issued token in seconds.                                                                                                                                                                                                                                          |
| `scope`             | OPTIONAL  | Scopes tied to the newly issued token. When the actual set of scopes tied to the newly issued token is different from the set requested by the token exchange request, this response parameter is REQUIRED.                                                                                 |
| `refresh_token`     | OPTIONAL  | A refresh token (cf. [RFC 6749](https://www.rfc-editor.org/rfc/rfc6749.html) [Section 6. Refreshing an Access Token](https://www.rfc-editor.org/rfc/rfc6749.html#section-6)).                                                                                                               |

## Support in Authlete

This section describes Authlete's support for Token Exchange.

[RFC 8693](https://www.rfc-editor.org/rfc/rfc8693.html) is supported by Authlete 2.3 onwards.

### Token Exchange Request

### "action" value of /auth/token API response

On receiving a token request from a client, an authorization server will send the request content to Authlete's [`/auth/token`](https://docs.authlete.com/en/shared/latest#post-/api/auth/token) API as one of request parameters. This API will make a response that includes `TOKEN_EXCHANGE` as a value of `action` parameter if the following conditions are met:

* The value of the `grant_type` request parameter of the token request is `urn:ietf:params:oauth:grant-type:token-exchange`
* The request passes basic validation steps which are performed on Authlete server side

The following table lists response parameters related to Token Exchange in a response from the `/auth/token` API.

| Response Parameter   | Type         | Description                                                                                                                                                                                                              |
| :------------------- | :----------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `resources`          | string array | The values of the `resource` request parameters.                                                                                                                                                                         |
| `audiences`          | string array | The values of the `audience` request parameters.                                                                                                                                                                         |
| `scopes`             | string array | The scopes listed in the `scope` request parameter.                                                                                                                                                                      |
| `requestedTokenType` | string       | A string representing the `requested_token_type` request parameter such as `"ACCESS_TOKEN"`. (cf. [TokenType.java](https://authlete.github.io/authlete-java-common/com/authlete/common/types/TokenType.html))            |
| `subjectToken`       | string       | The value of the `subject_token` request parameter.                                                                                                                                                                      |
| `subjectTokenType`   | string       | A string representing the value of the `subject_token_type` request parameter such as `"ACCESS_TOKEN"`. (cf. [TokenType.java](https://authlete.github.io/authlete-java-common/com/authlete/common/types/TokenType.html)) |
| `subjectTokenInfo`   | object       | Information about the subject token. Available only when the token type is either access token or refresh token.                                                                                                         |
| `actorToken`         | string       | The value of the `actor_token` request parameter.                                                                                                                                                                        |
| `actorTokenType`     | string       | A string representing the value of the `actor_token_type` request parameter such as `"ACCESS_TOKEN"`. (cf. [TokenType.java](https://authlete.github.io/authlete-java-common/com/authlete/common/types/TokenType.html))   |
| `actorTokenInfo`     | object       | Information about the actor token. Available only when the token type is either access token or refresh token.                                                                                                           |

### Token Validation

Regarding validation on input tokens, the specification states as follows.

> In processing the request, the authorization server MUST perform the appropriate validation procedures for the indicated token type and, if the actor token is present, also perform the appropriate validation procedures for its indicated token type. The validity criteria and details of any particular token are beyond the scope of this document and are specific to the respective type of token and its content.

It means that an authorization server MUST perform an appropriate validation, but the RFC 8693 doesn't define any details about token validation and leaves them to authorization server implementations. To reduce the burden of authorization servers, Authlete's `/auth/token` API performs the following validation.

| No. | Validation                                                                                                                                                                                               |
| :-: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|  1  | Confirm that the value of the `requested_token_type` request parameter is one of the registered token type identifiers if the request parameter is given and its value is not empty.                     |
|  2  | Confirm that the `subject_token` request parameter is given and its value is not empty.                                                                                                                  |
|  3  | Confirm that the `subject_token_type` request parameter is given and its value is one of the registered token type identifiers.                                                                          |
|  4  | Confirm that the `actor_token_type` request parameter is given and its value is one of the registered token type identifiers if the `actor_token` request parameter is given and its value is not empty. |
|  5  | Confirm that the `actor_token_type` request parameter is not given or its value is empty when the `actor_token` request parameter is not given or its value is empty.                                    |

Furthermore, Authlete performs additional validation on the tokens specified by the `subject_token` request parameter and the `actor_token` request parameter according to their respective token types as shown below.

### Token type: JWT

| No. | Validation                                                                                                                                                                                                                                   |
| :-: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|  1  | Confirm that the format conforms to the JWT specification ([RFC 7519 JSON Web Token (JWT)](https://www.rfc-editor.org/rfc/rfc7519.html)).                                                                                                    |
|  2  | Check if the JWT is encrypted and if it is encrypted, then (a) reject the token exchange request when the `tokenExchangeEncryptedJwtRejected` flag of the service is `true` or (b) skip remaining validation steps when the flag is `false`. |
|  3  | Confirm that the current time has not reached the time indicated by the `exp` claim if the JWT contains the claim.                                                                                                                           |
|  4  | Confirm that the current time is equal to or after the time indicated by the `iat` claim if the JWT contains the claim.                                                                                                                      |
|  5  | Confirm that the current time is equal to or after the time indicated by the `nbf` claim if the JWT contains the claim.                                                                                                                      |
|  6  | Check if the JWT is signed and if it is not signed, then (a) reject the token exchange request when the `tokenExchangeUnsignedJwtRejected` flag of the service is `true` or (b) finish validation on the input token.                        |
|  7  | (The signature of the JWT is not verified.)                                                                                                                                                                                                  |

<Note>
  Authlete does not validate an encrypted JWT because there is no standard way to obtain the key to decrypt the JWT with. This means that **you must validate an encrypted JWT by yourself** when one is used as an input token with the token type `urn:ietf:params:oauth:token-type:jwt` (if `tokenExchangeEncryptedJwtRejected` of your service is `false`).
</Note>

<Note>
  Authlete does not verify the signature of the JWT because there is no standard way to obtain the key to verify the signature of a JWT with. This means that **you must verify the signature by yourself** when a signed JWT is used as an input token with the token type `urn:ietf:params:oauth:token-type:jwt`.
</Note>

### Token type: Access Token

| No. | Validation                                                                                             |
| :-: | :----------------------------------------------------------------------------------------------------- |
|  1  | Confirm that the token is an access token that has been issued by the Authlete server of your service. |
|  2  | Confirm that the access token has not expired.                                                         |
|  3  | Confirm that the access token belongs to the service.                                                  |

<Note>
  The validation steps above imply that access tokens issued by other systems cannot be used as a subject token or an actor token with the token type `urn:ietf:params:oauth:token-type:access_token`. Authlete may provide a configuration option to disable the validation steps in the future, but it is not planned at the time of this writing.
</Note>

### Token type: Refresh Token

| No. | Validation                                                                                             |
| :-: | :----------------------------------------------------------------------------------------------------- |
|  1  | Confirm that the token is a refresh token that has been issued by the Authlete server of your service. |
|  2  | Confirm that the refresh token has not expired.                                                        |
|  3  | Confirm that the refresh token belongs to the service.                                                 |

<Note>
  The validation steps above imply that refresh tokens issued by other systems cannot be used as a subject token or an actor token with the token type `urn:ietf:params:oauth:token-type:refresh_token`. Authlete may provide a configuration option to disable the validation steps in the future, but it is not planned at the time of this writing.
</Note>

### Token type: ID Token

| No. | Validation                                                                                                                                                                                                                                        |
| :-: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|  1  | Confirm that the format conforms to the JWT specification ([RFC 7519 JSON Web Token (JWT)](https://www.rfc-editor.org/rfc/rfc7519.html)).                                                                                                         |
|  2  | Check if the ID Token is encrypted and if it is encrypted, then (a) reject the token exchange request when the `tokenExchangeEncryptedJwtRejected` flag of the service is `true` or (b) skip remaining validation steps when the flag is `false`. |
|  3  | Confirm that the ID Token contains the `exp` claim and the current time has not reached the time indicated by the claim.                                                                                                                          |
|  4  | Confirm that the ID Token contains the `iat` claim and the current time is equal to or after the time indicated by the claim.                                                                                                                     |
|  5  | Confirm that the current time is equal to or after the time indicated by the `nbf` claim if the ID Token contains the claim.                                                                                                                      |
|  6  | Confirm that the ID Token contains the `iss` claim and its value is a valid URI. In addition, confirm that the URI has the `https` scheme, no query component and no fragment component.                                                          |
|  7  | Confirm that the ID Token contains the `aud` claim and its value is a JSON string or an array of JSON strings.                                                                                                                                    |
|  8  | Confirm that the value of the `nonce` claim is a JSON string if the ID Token contains the claim.                                                                                                                                                  |
|  9  | Check if the ID Token is signed and if it is not signed, then (a) reject the token exchange request when the `tokenExchangeUnsignedJwtRejected` flag of the service is `true` or (b) finish validation on the input token.                        |
|  10 | Confirm that the signature algorithm of the ID Token is asymmetric.                                                                                                                                                                               |
|  11 | Verify the signature of the ID Token.                                                                                                                                                                                                             |

<Note>
  Authlete does not validate an encrypted ID Token because there is no standard way to obtain the key to decrypt the ID Token with in the context of token exchange where the client ID for the encrypted ID Token cannot be determined. This means that **you must validate an encrypted ID Token by yourself** when one is used as an input token with the token type `urn:ietf:params:oauth:token-type:id_token` (if `tokenExchangeEncryptedJwtRejected` of your service is `false`).
</Note>

<Note>
  The 10th validation step above implies that ID Tokens whose signature algorithm is symmetric (`HS256`, `HS384` or `HS512`) cannot be used as a subject token or an actor token with the token type `urn:ietf:params:oauth:token-type:id_token`. It is because the symmetric key to verify the signature with (i.e. a client secret) cannot be determined in the context of token exchange.
</Note>

<Note>
  Signature verification is performed even in the case where the issuer of the ID Token is not your service. But in that case, the issuer must support the discovery endpoint defined in [OpenID Connect Discovery 1.0](https://openid.net/specs/openid-connect-discovery-1_0.html). Otherwise, signature verification fails.
</Note>

### Token type: SAML 1.1 Assertion

| No. | Validation                                                      |
| :-: | :-------------------------------------------------------------- |
|  1  | (Authlete does not perform any validation for this token type.) |

### Token type: SAML 2.0 Assertion

| No. | Validation                                                      |
| :-: | :-------------------------------------------------------------- |
|  1  | (Authlete does not perform any validation for this token type.) |

### Token Exchange Response

### /auth/token/create API

The authorization server performs necessary validation based on the response from the `/auth/token` API to determine what kind of token is issued, and make a token exchange response to the client.

The server uses Authlete's [/auth/token/create](https://docs.authlete.com/en/shared/latest#post-/api/auth/token/create) API to create the token exchange response, by specifying `TOKEN_EXCHANGE` as a value of `grantType`, which is one of request parameters to the API.

## Configuring Token Exchange

To configure Token Exchange in Authlete, follow these steps:

### Service Configuration

1. Log in to the [Authlete Management Console](https://console.authlete.com).
2. Navigate to **Service Settings**.
3. Go to **Endpoints > Global Settings > Supported Grant Types** and enable `TOKEN_EXCHANGE` grant.
   ![](https://storage.googleapis.com/authlete-website/resources/token_exchange/0.png)
4. Go to **Tokens and Claims > Advanced > Token Exchange**.
5. Review and enable any necessary flags to tighten the security of your Token Exchange configuration.
6. Click **Save Changes** to apply the configuration.

![](https://storage.googleapis.com/authlete-website/resources/token_exchange/1.png)

To ensure secure token exchange, you need to define additional configurations outside the scope of [RFC 8693](https://www.rfc-editor.org/rfc/rfc8693.html). Authlete provides the following options for this purpose:

| **Configuration Option**  | **Type** | **Description**                                                           |
| ------------------------- | -------- | ------------------------------------------------------------------------- |
| Identifiable Clients Only | boolean  | Rejects token exchange requests from unidentifiable clients.              |
| Confidential Clients Only | boolean  | Rejects token exchange requests from public clients.                      |
| Permitted Clients Only    | boolean  | Rejects token exchange requests from clients without explicit permission. |
| Reject Encrypted JWT      | boolean  | Rejects token exchange requests using encrypted JWTs as input tokens.     |
| Reject Unsigned JWT       | boolean  | Rejects token exchange requests using unsigned JWTs as input tokens.      |

### Client Configuration

1. Navigate to **Client Settings** of your desired client.
2. Go to **Tokens and Claims > Advanced > Token Exchange**.
3. Enable **Explicit Permission for Token Exchange** to grant this client explicit permission to perform token exchange requests. This setting ensures that only authorized clients can perform token exchanges, especially when the service is configured to restrict token exchange to permitted clients.
4. Click **Save Changes** to finalize the configuration.

![](https://storage.googleapis.com/authlete-website/resources/token_exchange/2.png)

## Examples

### Authorization Server Implementation

### Processing the TOKEN\_EXCHANGE Action

Authorization server implementations have to process the `TOKEN_EXCHANGE` action to support Token Exchange. The `switch` statement below excerpted from [TokenRequestHandler.java](https://github.com/authlete/authlete-java-jaxrs/blob/master/src/main/java/com/authlete/jaxrs/TokenRequestHandler.java) in the [authlete-java-jaxrs](https://github.com/authlete/authlete-java-jaxrs/) library is an example of processing the `TOKEN_EXCHANGE` action. The `switch` statement has a `case` entry for `TOKEN_EXCHANGE`.

```java theme={null}
// Dispatch according to the action.
switch (action)
{
    case INVALID_CLIENT:
        // 401 Unauthorized
        return ResponseUtil.unauthorized(content, CHALLENGE);

    case INTERNAL_SERVER_ERROR:
        // 500 Internal Server Error
        return ResponseUtil.internalServerError(content);

    case BAD_REQUEST:
        // 400 Bad Request
        return ResponseUtil.badRequest(content);

    case PASSWORD:
        // Process the token request whose flow is "Resource Owner Password Credentials".
        return handlePassword(response);

    case OK:
        // 200 OK
        return ResponseUtil.ok(content);

    case TOKEN_EXCHANGE:
        // Process the token exchange request (RFC 8693)
        return handleTokenExchange(response);

    case JWT_BEARER:
        // Process the token request which uses the grant type
        // urn:ietf:params:oauth:grant-type:jwt-bearer (RFC 7523).
        return handleJwtBearer(response);

    default:
        // This never happens.
        throw getApiCaller().unknownAction("/api/auth/token", action);
}
```

### Processing token exchange requests

[TokenExchanger.java](https://github.com/authlete/java-oauth-server/blob/master/src/main/java/com/authlete/jaxrs/server/api/TokenExchanger.java) in **[java-oauth-server](https://github.com/authlete/java-oauth-server)**, an open-source sample implementation of authorization server written in Java, is a sample implementation of processing a token exchange request.

Note that the implementation is just an example, and not intended for production use.

### Request and Response Example

### 1. Prepare an ID Token in some way or other.

```shell theme={null}
$ ID_TOKEN=eyJraWQiOiJhdXRobGV0ZS1mYXBpZGV2LWFwaS0yMDE4MDUyNCIsImFsZyI6IlJTMjU2In0.eyJpc3MiOiJodHRwczovL2ZhcGlkZXYtYXMuYXV0aGxldGUubmV0LyIsInN1YiI6IjEwMDQiLCJhdWQiOlsiNTg5OTQ2MzYxNDQ0ODA2MyJdLCJleHAiOjE2NTg2NzExMzAsImlhdCI6MTY1ODY3MDgzMCwiYXV0aF90aW1lIjoxNjU4NjcwODMwLCJub25jZSI6IjEyMzQ1Njc4OSIsInZlcmlmaWVkX2NsYWltcyI6eyJ2ZXJpZmljYXRpb24iOnsidHJ1c3RfZnJhbWV3b3JrIjoibmlzdF84MDBfNjNBIn0sImNsYWltcyI6eyJnaXZlbl9uYW1lIjoiSW5nYSIsImZhbWlseV9uYW1lIjoiU2lsdmVyc3RvbmUiLCJiaXJ0aGRhdGUiOiIxOTkxLTExLTA2IiwiOmFnZV8xOF9vcl9vdmVyIjpudWxsfX19.mxE8FQaDb0edY_rWasSQ7pEMXbFon7oWr-Ccv1dB15q8eh2MaKRGrgvwPw_XjAdXlMNzkcV6iEUjRUvLGTvzm7_45cdoOxRX1xWzQw-vwvRbM46xd3Yht3EVjyRUUBJ_92J1yBmu7Nn93rygcnCE-fC_bSTSIJWgEnoC7dpxHYnoJ2QHrIOYFMBAA_3ZYCLGpgiWbIZnB2D1ib2eqwJ9zoJqeFNEBhXo9ThYkASHYaG-ZWofy7364lgeV4Rqy1r4XqzchFRW4yzWs_IM72bTtXTUkstlNOxZU12KEz50uVhtcOXv06iI71I9vceRP-ZVICpq7Knt0vEKWTM41E3ziw
```

### 2. Make a token exchange request.

```shell theme={null}
$ curl http://localhost:8080/api/token -d grant_type=urn:ietf:params:oauth:grant-type:token-exchange -d subject_token=$ID_TOKEN -d subject_token_type=urn:ietf:params:oauth:token-type:id_token -d client_id=5908895171 -d scope=email
```

### 3. Receive a token exchange response.

```json theme={null}
{
  "access_token":"NEdL-q9EfOI4S5XzaMeimXAXVqS139Jm9DTYeLUAd5o",
  "issued_token_type":"urn:ietf:params:oauth:token-type:access_token",
  "token_type":"Bearer",
  "expires_in":86400,
  "scope":"email",
  "refresh_token":"pK9f5OWIrx58_XWrE_SpCLLN-BM673ljliTSffjqwao"
}
```
