Auth0 Integration

If you are already using Auth0 as your identity provider, it is easy to configure Auth0 to generate access tokens that will give your end-users access to the Fusebit platform. Your front-end application can request these access tokens from Auth0 directly, without having to call into your application's back-end systems. Best of all, the entire authentication flow is entirely transparent to the end-user; the end-user only needs to sign-in to your application as he or she normally would. This makes integrating the Fusebit editor into your application even easier.

For the purposes of this guide, we'll assume that we already have an application configured with Auth0 for the Sales Anchor SaaS web application. This web application is a Single-Page App (SPA) that we setup following this Auth0 Quick Start. In the web application we are already using the Auth0 WebAuth JS object for the Sales Anchor application itself:

this.salesAnchorWebAuth = new auth0.WebAuth({
  domain: 'sales-anchor.auth0.com',
  clientID: '<client id>',
  redirectUri: window.location.href,
  audience: 'https://sales-anchor.com',
  responseType: 'token id_token',
  scope: 'openid profile',
});

After the login redirect with Auth0 completes, the following code in the Sales Anchor web application captures the access token that is used with Sales Anchor's own backend service:

function getAccessToken(callback) {
  this.salesAnchorWebAuth.parseHash((error, decodedHash) => {
    if (error) {
      return callback(error);
    }

    const accessToken = decodedHash.accessToken;
    callback(null, accessToken);
  });
}

Creating an API for Fusebit

The first step is to configure an API for Fusebit within the Auth0 Dashboard. This Auth0 guide explains how to create a new API. When creating the API, use the following values:

  • Name - Fusebit Platform
  • Identifier - https://api.{region}.fusebit.io
  • Signing Algorithm - RS256

After creating the Fusebit Platform API, go to the settings tab and be sure to enable Allow Skipping User Consent under the 'Access Settings' section.

Requesting Fusebit Access Tokens

With Auth0 now configured, we can update the Sales Anchor SaaS web application to request Fusebit access tokens.

First we need to create another Auth0 WebAuth JS object for the Fusebit platform. We can do this in the same place in the application that we created the first WebAuth object for Sales Anchor itself:

this.salesAnchorWebAuth = new auth0.WebAuth({
  domain: 'sales-anchor.auth0.com',
  clientID: '<client id>',
  redirectUri: window.location.href,
  audience: 'https://sales-anchor.com',
  responseType: 'token id_token',
  scope: 'openid profile',
});

this.fusebitWebAuth = new auth0.WebAuth({
  domain: 'sales-anchor.auth0.com',
  clientID: '<client id>',
  redirectUri: window.location.href,
  audience: 'https://api.{region}.fusebit.io',
  responseType: 'token',
  scope: 'openid',
});

Notice that the domain and the clientId values are the same for both WebAuth instances. The important difference is the audience value, which is now set to the identifier for the API that we created in the Auth0 dashboard previously. Also, we only need access tokens for the Fusebit platform, so the responseType value is just token and the Fusebit platform does not need the end-user's profile so the profile scope has been removed.

With the WebAuth instance created for the Fusebit platform, we can now update the code to get an access token for the Fusebit editor after the end-user signs in to the Sales Anchor web application.

function getAccessTokens(callback) {
  this.salesAnchorWebAuth.parseHash((error, salesAnchorDecodedHash) => {
    if (error) {
      return callback(error);
    }

    this.fusebitWebAuth.checkSession({ prompt: 'none' }, (error, fusebitDecodedHash) => {
      if (error) {
        return callback(error);
      }

      const accessTokens = {
        salesAnchor: salesAnchorDecodedHash.accessToken,
        fusebit: fusebitDecodedHash.accessToken,
      };
      callback(null, accessTokens);
    });
  });
}

Because the end-user has just signed in, we can use the checkSession() method of the WebAuth instance and specify no prompt. This ensures that requesting the access token is transparent to the end-user.

The Fusebit access token above can now be used with the embedded Fusebit editor.

Local Development

It is important to note that when doing local development, it is not possible to skip user consent. If the Auth0 redirect URL is to localhost the above checkSession({ prompt: 'none' }) call will fail unless the end-user (in this case, the developer testing the application) has explicitly consented to allow the Fusebit API.

To work around this, we can update the getAccessTokens() code in the following manner:

function getAccessTokens(callback) {
  this.salesAnchorWebAuth.parseHash((error, salesAnchorDecodedHash) => {
    if (error) {
      return callback(error);
    }

    this.fusebitWebAuth.checkSession({ prompt: 'none' }, (error, fusebitDecodedHash) => {
      if (error) {
        if (error.code === 'consent_required' || error.code === 'interaction_required') {
          // After the authorize redirect flow for the Fusebit API, the code should
          // initiate sign-in again for the Sales Anchor application, so that we'll
          // enter the 'getAccessTokens()' code path a second time. However, the second time
          // the 'checkSessions()' call will succeed because consent has been given.
          return this.fusebitWebAuth.authorize();
        }
        return callback(error);
      }

      const accessTokens = {
        salesAnchor: salesAnchorDecodedHash.accessToken,
        fusebit: fusebitDecodedHash.accessToken,
      };
      callback(null, accessTokens);
    });
  });
}

Note that this local development solution requires the code to initiate sign-in again for the Sales Anchor application itself after consent for the Fusebit API has been given. This is not a requirement by any means, but probably the simplest way to solve local development issue. How you implement the exact mechanics of this will be application dependent.


Did this page help you?