OAuth Token exchange support
Last updated
Last updated
The current release of the INDIGO IAM implements part of the Token Exchange OAuth specification. The Token Exchange OAuth specification defines "a lightweigth protocol that enables clients to request and obtain security tokens from authorization servers".
OAuth 2.0 was designed to solve the problem of a delegated access to resources across services, mediated by an authorization server, as shown in the following picture:
In the picture above we have the usual OAuth roles:
The user (or resource owner, in OAuth terminology);
A resource server, ie. a service hosting user resources, capable of
accepting and responding to protected resource requests using access tokens.
A client: this is an agent that has received a permission from the user to
act on his behalf on his resources hosted on a resource server;
An authorization server: a service that issues access token to clients after
having authenticated the user and obtained an authorization from the user
that the client is entitled to act on user's resources
There are scenarios when a resource server, in order to satisfy a client request, needs to access resources hosted by other downstream services on behalf of the user, like in the following picture:
In OAuth, access tokens are bearer tokens, so the first resource server could simply use the access token received from the client to interact, on behalf of the user, with the downstream resource server.
There are, however, situations in which just using the received access token against the downstream service is not possible, like for instance if the token audience was scoped to be valid only on the first resource server.
Moreover, the resource server could need the ability to act on behalf of the user for an unbounded amount of time (e.g., to implement long-running computations), not limited by the validity of the received access token.
The token exchange specification was designed to provide a protocol in support of these scenarios, where a client can exchange an access token received from antoher client with a new token (or a set of tokens, as we will see) by interacting with a trusted OAuth authorization server.
As specified in the Token Exchange OAuth specification, when a subject A impersonates B, A has all the rights of B and it is indistinguishable from B. So, when A interacts within any other entity, A is B.
With delegation A still has its own identity, separate from B. So when A interacts within another entity, it is explicit that A is representing B, because B has delegated some of its rights to A.
More details about the difference from this two semantics can be found in this section of the specification.
The INDIGO IAM token exchange implementation currently supports only impersonation semantics.
In order to request a token exchange, a client must be configured with the urn:ietf:params:oauth:grant-type:token-exchange
grant type enabled. The token exchange grant type is disabled by default for dynamically registered clients, and can be enabled only by users with administrative privileges on the IAM.
A client who wants to exchange an access token with a new one (or a couple of new tokens, in case a refresh token is requested), must send an authenticated request to the IAM /token
endpoint, specifying the following properties:
Parameter
Value
grant_type
urn:ietf:params:oauth:grant-type:token-exchange
subject_token
The subject access token that the client wants to exchange
scope
The set of scopes requested for the new access token
audience
Optional. A space-separated list of resource identifiers that will be used to limit the audience of the issued token
A client, when requesting a token exchange, can request any of the scopes enabled by its client configuration. IAM system scopes are however handled in a special way. These scopes, in order to be "exchanged" across clients, need to be
enabled for the client requesting the token exchange
linked to the subject token presented for the token exchange
The list of system scopes currently defined in the IAM can be obtained by registered users by issuing a request to the IAM system scopes API:
This section describes a token exchange flow.
We start with a normal OAuth flow where a client, token-exchange-subject
, requests an access token from the IAM using the resource owner password credential flow. The token-exchange-subject
client is configured to use HTTP basic authentication against the IAM token endpoint, and in this example acts on behalf of the test
user. We use the resource owner password credentials flow for convenience, but any other OAuth or OpenID connect flow that involves a user identity would be fine (i.e., authorization code).
Note that the only scopes requested in this first request are openid
and profile
, i.e. the scopes required to access user identity information. IAM token endpoint returns a JSON containing an access token and other info:
We put this access token in an environment variable:
We use this access token to access the app
API, which only requires access to user identity to grant access:
Suppose now that the app
API needs, to properly answer the request from the client, to interact with another downstream service, https://tasks.example.org, on behalf of the user. Unfortunately the set of scopes linked to the access token received are not sufficient to do this, and so app
decides to exchange the token received with another one granting enough privileges.
In Token Exchange terms, here app
is the actor
, the subject identity linked to the token is the test
user, and the audience for the new token being requested would be the https://tasks.app.example.org/api
API.
So app
would do a request like the following:
Note that app
requests an additional scope, read-tasks
, to interact with the downstream service.
Since app
is a trusted client for token exchange, the IAM responds with the following JSON:
And app
can use the newly issued access token to invoke services on https://task-app.example.org/api on behalf of user test
:
Clients that have the token exchange grant enabled are considered trusted clients i.e., no explicit grant from the user is needed to grant access to client scopes. For IAM system scopes, however, these can be "exchanged" only if linked to the original subject token.
The current implementation of Token Exchange in Indigo IAM has the following limitations:
Delegation is not yet supported: if actor_token
or the want_composite
parameters are specified within the request, an error response is returned by
the authorization server;
The resource
field is ignored.