Implementation Guide

The Token Exchange flow provides a way to allow Applications with the same Provider to exchange data with the User's consent.

This flow is meant to be implemented on a server-side application that can secretely store secrets, it is not meant to be used for a Single Page Application (SPA) or a front-side only Application or a native Application (mobile or desktop).

When should you use this flow?

Let’s assume your are one of the developers of Application A.

Here is a basic scenario where you should use a Token Exchange flow:

  • You log your Users by asking your Provider for an access_token.

  • You know that Application B is also logging Users via the same Provider, and has exposed an endpoint that gives access to User Data.

  • Application B declared this scope of User Data before the Provider.

  • You want to access your User Data that is stored by Application B.

Here is the basic process you need to go through:

  1. A User X logs in your Application A (so Application A receives an access_token for User X).

  2. Your Application A uses User X’s access_token to require an exchange_token that Application B can trust, so Application A can access the endpoint of Application B in the name and with the consent of User X.

What is different from the other access tokens?

Most access_tokens (like those obtained via the Authorization Code Flow for example) are used to make sure your Application can trust User requests.

access_tokens issued during a Token Exchange flow are a way to prove the Application you want to request (in our example, Application B) that your Application (in our example, Application A) has received the User’s consent.

Setting up

To be able to request an exchange_token, you will first need to be in possession of the access_token that you receive for your User during an Authorization Code Flow. In the Token Exchange flow, this first access_token is called subject_token. Additionally, the scope contained in the subject_token (those requested in the Authorization Code Flow where you got this token) must be a superset of those required in the Token Exchange flow.

Note
The length of tokens can vary and exceed 255 characters. Keep this in mind, as if you want to store them in a database as a VARCHAR will not be large enough.

Request

The request is a POST to the <token_endpoint>, the parameters must be encoded using the "application/x-www-form-urlencoded" format. The following parameters need to be included:

  • grant_type : The value of this parameter must be "urn:ietf:params:oauth:grant-type:token-exchange". It indicates that a Token Exchange is being performed.

  • scope: A list of space-delimited, case-sensitive strings. These strings represent the kind of informations and actions that Application A will be able to access and perform on the Application B, in the name of User X. The scope specified in the request should be a sublist of those requested when you got the subject_token.

  • subject_token : A security token that represents the identity of the User on behalf of whom the request is being made (in our example User X).

  • subject_token_type : represents the type of the above token, should be : "urn:ietf:params:oauth:token-type:access_token".

Code Sample

Caution
The following code is not production ready
const request = require("request");
const jwt = require("jsonwebtoken");

const payload = {
  grant_type: "urn:ietf:params:oauth:grant-type:token-exchange",
  scope: "<the scopes you want to require>",
  subject_token: "<the access token your user got after logging in your app>",
  subject_token_type: "urn:ietf:params:oauth:token-type:access_token"
};

request.post(
  "https://[providerFQDN]/oauth/token",
  { form: payload },
  function(err, httpResponse, body) {
    if (httpResponse && (httpResponse.statusCode === 200)) {
      const json_response = JSON.parse(body);
      const token_exchange = json_response.access_token;
      // Yay! 🤗 You can now use `access_token` to request Applications in your provider ecosystem

      request.get(
        "https://anotherapp.example.com/protected-endpoint",
        {headers: {'Authorization': `Bearer ${token_exchange}`}},
        function(err, httpResponse, body) {
          // Do pretty things with your brand new authorization
        }
      )
    } else {
      // something went wrong
    }
  }
);
Table of Content