ForgeRock Developer Experience

Implement ForgeRock Token Vault code

There are three main components to configure when implementing the ForgeRock Token Vault. It is important the configuration is consistent between these components. To achieve this, you could add your shared configuration to a .env file in the root of your project.

In the following examples, the configuration uses literal values to help understand the values required.

Implement main app code

This configuration should be within your app’s index or main file.

Initialize the ForgeRock Token Vault client:

app/src/main.js
import { Config, TokenManager } from '@forgerock/javascript-sdk';
import { client } from '@forgerock/token-vault';

/**
 * This factory function takes in a config object and returns
 * the necessary methods to setup the iframe ("proxy"), the
 * service worker ("interceptor"), and the token store replacement
 * API ("store").
 */
const register = client({
    app: {
        origin: 'https://app.example.com',
    },
    interceptor: {
        file: '/interceptor.js',
    },
    proxy: {
        origin: 'https://proxy.example.com',
    },
});

/**
 * Sets up the service worker for intercepting fetch requests
 */
register.interceptor({
    /* optional interceptor worker config */
});

/**
 * Injects the iframe into the DOM to setup the proxy
 * Make sure to pass in the required, real DOM element as the zeroeth argument
 */
register.proxy(document.getElementById('token-vault'), {
    /* optional proxy config */
});

/**
 * Creates the store replacement for the SDK
 */
const tokenVaultStore = register.store({
    /* optional store config */
});

In the same file, configure the SDK:

app/src/main.js
Config.set({
  clientId: 'ForgeRockSDKClient',
  redirectUri: location.href,
  scope: 'openid profile email address',
  serverConfig: {
    baseUrl: 'https://openam-forgerock-sdks.forgeblocks.com/am',
    timeout: 5000,
  },
  realmPath: 'alpha',
  // Replace the default token store with Token Vault's store
  tokenStore: tokenVaultStore,
});

Implement Token Vault Interceptor code

This configuration should be within the Service Worker’s entry file, which is separate from your main application code.

This is also the file to which your client() method config object property of interceptor.file method references.

Reference this file in your main application when calling the client() method, as the interceptor.file property.

Example configuration is as follows:

app/interceptor/interceptor.js
import { interceptor } from '@forgerock/token-vault';

interceptor({
  interceptor: {
    // Use either fully qualified URLs
    // Or end with a single asterisk as a wildcard
    urls: [/* Your protected endpoint URLs */],
  },
  forgerock: {
    // MUST match what you configured in your main app
    serverConfig: {
      baseUrl: 'https://openam-forgerock-sdks.forgeblocks.com/am',
      timeout: 5000,
    },
    realmPath: 'alpha',
  },
});

The interceptor.urls array accepts a /* ending to match any request from a particular root domain and path. This means you do not have to list each and every unique protected endpoint that your app might use.

For example, https://backend.example.com/resources/protected/*

This is not a full glob-pattern feature - just a single trailing wildcard.

Implement Token Vault Proxy code

This configuration should be within the Token Vault Proxy entry file.

Example configuration is as follows:

proxy/src/proxy.js
import { proxy } from '@forgerock/token-vault';

proxy({
  app: {
    // This MUST match the origin where your main app runs
    origin: 'https://app.example.com',
  },
  forgerock: {
    //  MUST match the config in your main app and interceptor
    clientId: 'ForgeRockSDKClient',
    redirectUri: location.href,
    scope: 'openid profile email address',
    serverConfig: {
      baseUrl: 'https://openam-forgerock-sdks.forgeblocks.com/am',
      timeout: 5000,
    },
    realmPath: 'alpha',
  },
});

Build the code

The ForgeRock Token Vault requires more complex building and bundling configuration than a regular JavaScript app that uses the SDK because it requires three different bundles:

  1. The main application

  2. The Token Vault Interceptor (Service Worker)

  3. The Token Vault Proxy (iframe)

You can often use a default configuration for the main application and the Token Vault Proxy when using any of the popular bundlers, such as Webpack or Vite

The Token Vault Interceptor requires a specific build configuration to ensure maximum compatibility with various browsers.

Bundling the Interceptor

To provide the best cross-browser support, the Token Vault Interceptor requires a dedicated bundle configuration so that it results in a single-file output, down-leveled to at least ES2020 without any ES Module syntax.

We recommend using a separate vite.interceptor.config.js or webpack.interceptor.config.js for the Token Vault Interceptor, as well as a build separate command that consumes this separate configuration file.

If you are using Vite, you might achieve the best results with bundling into an Immediately Invoked Function Expression (IIFE).

If you are using Webpack, its defaults are good for bundling the Token Vault Interceptor.

Next steps

After you implement the code to enable the ForgeRock Token Vault, you can update your app to obtain tokens using origin isolation.