Token exchange grant handler SPI

1. Introduction

OAuth 2.0 token exchange (RFC 8693) is a generic mechanism for client applications to obtain a token from the token endpoint of an authorisation server by presenting a grant that is also a token.

Example token exchange scenarios:

  • Obtaining tokens for backend and downstream services.
  • Obtaining tokens in a delegation (on-behalf-of) scenario.
  • Obtaining tokens in a impersonation (act-as) scenario.
  • Obtaining tokens using a credential from a different security domain.
  • Obtaining tokens for special purposes.

The decision what scope and properties to give the newly issued token is based on the authorisation encoded in the submitted token, and may also take into account the identity and registered metadata of the requesting client.

The nature of the OAuth 2.0 token exchange grant is similar to the JWT assertion grants, but giving architects complete freedom to specify the type, encodings and other properties of the submitted and issued tokens. In the common case the submitted and the issued tokens are both access tokens, but they can also be combinations of a generic JWT, an ID token, a SAML assertion or something else.

1.1 Example token exchange request

This example illustrates the request for an access token with scope https://api.example.com/get-customer-address using another token with scope https://api.example.com/order-delivery.

Note that with token exchange the submitted token can originate from a different security domain (provided it's trusted).

The client submits the original token in the subject_token form parameter, indicating its type (access token) in the subject_token_type parameter. The grant_type and scope parameters have their standard meanings from the core OAuth 2.0 spec.

The form parameters also include a private_key_jwt client authentication.

POST /token HTTP/1.1
Host: c2id.com
Content-Type: application/x-www-form-urlencoded

grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Atoken-exchange
 &subject_token=Eexungahcaetaizoh7ingait3Ur9ya1b
 &subject_token_type=urn%3Aietf%3Aparams%3Aoauth%3Atoken-type%3Aaccess_token
 &scope=https%3A%2F%2Fapi.example.com%2Fget-customer-address
 &client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer
 &client_assertion=eyJhbGciOiJSUzI1NiIsImtpZCI6IjIyIn...

The Connect2id server authenticates the client and checks the submitted token. If the exchange is permitted it returns a successful token response:

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache

{
  "access_token"     : "2YotnFZFEjr1zCsicMWpAA",
  "token_type"       : "DPoP",
  "issued_token_type": "urn:ietf:params:oauth:token-type:access_token",
  "expires_in"       : 60,
  "scope"            : "https://api.example.com/get-customer-address"
}

Example error response if the submitted token is found to be invalid / expired, or the exchange was denied due to a violated policy:

HTTP/1.1 400 Bad Request
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache

{
  "error"             : "invalid_request",
  "error_description" : "Invalid token exchange request"
}

1.2 Prerequisites

For a client to make a token exchange request it must be registered for the urn:ietf:params:oauth:grant-type:token-exchange grant type.

1.3 Security considerations

Whenever possible, a client performing token exchange should be registered as confidential (with authenticating credentials) rather than public. This will limit the scope of potential token exploitation in case of a leak of a token that is exchange capable.

Clients that request highly privileged tokens should use a strong authentication method, such as private_key_jwt or one based on the mutual TLS profile.

2. Token exchange grant handler SPI

The Connect2id server comes with a flexible plugin interface (SPI) for verifying token exchange grants and specifying the properties of the access token to be issued.

Features of the grant handler SPI:

  • Provides access to the token request parameters, including the subject_token and the optional actor_token.

  • If the subject_token is a valid locally issued access token, self-contained or identifier-based, the Connect2id server makes its introspected authorisation details available to the handler.

  • The client_id and registered metadata of the requesting client is also made available, which may be as inputs in determining the properties of the issued access token (scope values, etc).

  • Provides optional methods for initialising, configuring and shutting down the handler.

At present the token exchange handler SPI is capable of ingesting access tokens (locally or externally issued) as well as other arbitrary tokens. The issued token can be a local access token. Future Connect2id server releases may add support for issuing refresh tokens and generic JWTs.

Access token JWT Refresh token ID token SAML 1.1 SAML 2.0
Submitted token
Issued token

How does the Connect2id server process token exchange requests?

  1. The Connect2id server validates the client_id and its credentials (for a confidential client). On failure to authenticate an invalid_client error is returned.

  2. The Connect2id server then invokes the token exchange grant handler plugin interface (SPI), which has 2 tasks to perform:

    1. Verify that the submitted subject_token and optional actor_token are valid and carry the necessary authorisation for an exchange. If not the handler must return an invalid_request error.
    2. Determine the scope of the access token to issue to the client. This is up to the handler's policy, and will typically be based on the scope of the submitted token, with the client metadata as potentially additional decision input. The grant handler can also set other token properties, such as expiration, encoding, etc.
  3. If the handler accepted the grant as valid it returns an access token spec which the Connect2id server will then use to mint the actual token and return it in a appropriate token response to the client.

The token exchange handler SPI was introduced in v12.14.

3. Available implementations

A token exchange grant handler that delegates processing to a web-service is planned for a future Connect2id server release.

4. How to develop your own client credentials grant handler

First, read our general guide for developing, annotating and packaging an SPI-based plugin.

The connector must implement the TokenExchangeGrantHandler SPI defined in the Connect2id server SDK:

Git repohttps://bitbucket.org/connect2id/server-sdk

If the Connect2id server detects an SPI implementation it will log its loading under OP7106.

INFO main MAIN - [OP7106] Loaded and initialized urn:ietf:params:oauth:grant-type:token-exchange grant handler com.nimbusds.openid.connect.provider.spi.grants.tokenexchange.handler.DelegationHandler

Note, the Connect2id server can load multiple token exchange grant handlers at startup, but only one may be enabled at a time.