Enable Your Embedded Visual Builder Application to Call CRM APIs

If you embed a Visual Builder application, then make the changes described below to enable your application to call CRM APIs using JSON Web Tokens (JWT).

After making these changes, your application can then use the JWT token passed to it via the iframe messaging API from Application Composer. This token eliminates the need to perform a redirect to IDCS to establish a security cookie, as well as the need to call the server to retrieve the current user's information.

To pass a JWT token to an embedded VB application, you must:

  1. Disable the service worker.

  2. Configure your VB application for embedding.

  3. Configure services for direct connection to FA applications.

  4. Add the security provider files to your application.

  5. Register the new security provider.

Note that you can do this provided that your application:

  • Makes REST calls against FA APIs, only

  • Doesn't request anything that requires the IDCS security token

  • Doesn't use permissions or roles for functional security logic within the browser application

1. Disable Service Worker

Add the following code to the end of your application's index.html, right before the closing body tag.

<script type="text/javascript">
  vbInitConfig['SERVICE_WORKER_CONFIG'] = { disabled: true };
</script>
Note: This is optional but recommended in order to reduce runtime overhead.

2. Configure Your Application for Embedding

To allow your application to be embedded as an iframe, see "Embed a Web App in an Oracle Cloud Application" in the Oracle Cloud Developing Applications with Oracle Visual Builder guide.

3. Configure Services for Direct Connection to FA

To support direct connections, Visual Builder service instances must use HTTPS. Ensure that the FA back end is the same server URL that's serving the embedded content. Also ensure that FA services don't go through the VB proxy and instead make a direct connection against the FA back end.

Select one of the connection authentication options below.

  • No defined authentication

  • Propagate Current User Identity

  • Direct (Bypass Authentication Proxy)

  • Oracle Cloud Account, Token relay enabled

  • User Assertion OAuth 2.0, Token relay enabled

  • Client Credentials OAuth 2.0, Token relay enabled

  • Resource Owner OAuth 2.0, Token relay enabled

For more information, see "Configure Connection and Authentication Types for Service Connections" in the Oracle Cloud Developing Applications with Oracle Visual Builder guide.

4. Add Security Provider Files

Copy and paste the JavaScript below into two .js files, and add them to the /webApps/{name}/resources/js directory.

Copy and paste this content into a file called FusionEmbeddedWithNoUserSecurityProvider.js.

define(['vb/types/securityProvider'],
  (SecurityProvider) => {
    class FusionEmbeddedWithNoUserSecurityProvider extends SecurityProvider {
      constructor() {
        super();
      }
      
      /**
       * Install our fetch handler to inject the JWT token from FA.
       */
      getServiceWorkerPlugins(config, isAnonymous) {
        return new Promise(r => r(['resources/js/InjectFATokenFetchPlugin']));
      }
      
      /**
       * Dummy method to return a user without any information, roles, or permissions. Used to skip the
       * traditional call to _currentusers for performance reasons
       */
      fetchCurrentUserRaw(config) {
        return new Promise((r) => {
          r({ response: { 
             ok: true
           },
           body: {
              userId: 'anonymous',
              username: 'anonymous',
              longId: 'anonymous',
              fullName: 'anonymous',
              email: 'anonymous',
              roles: [],
              permissions: [],
              isAdmin: false,
              isAuthenticated: true,
              isAnonymous: false
            }
          });
        });
      }
    }
    
    return FusionEmbeddedWithNoUserSecurityProvider;
 });
 

Next, copy and paste this content into a file called InjectFATokenFetchPlugin.js.

define(['vbsw/api/fetchHandlerPlugin'], function (FetchHandlerPlugin) {
  'use strict';

  class InjectFATokenFetchPlugin extends FetchHandlerPlugin {
      constructor(context) {
        super(context);
        
        // when initialized, start the request for the JWT token from the parent iframe
        this.waitForTokenInit = new Promise((resolve) => {
          const isEmbedded = window.location !== window.parent.location;

          if (isEmbedded) {
            window.addEventListener('message', event => {
              if (!event.origin.startsWith(window.frames.origin)) {
                resolve({
                  host: event.origin,
                  token: event.data
                });
              } 
              else {
                  return;
              }
            });

            const payload = {};
            payload.origin = window.frames.origin;
            payload.method = 'requestJwtToken';
            window.parent.postMessage(JSON.stringify(payload), '*');
          }
          
          // TODO: if we are not in an embedded iframe (ran directly from VB) we will use the following credentials
          // below. This must be changed to match the environment and current JWT token (using postman to retreive). 
          else {
            resolve({
              host: 'https://cccn.fa.em2.oraclecloud.com',
              token: "xxx ... xxx"
            });
          }
        });
      }

      handleRequestHook(request) {
        return this.waitForTokenInit.then((tokenInfo) => {
          if (request.url.indexOf(tokenInfo.host) === 0) {
            const headers = new Headers();
            request.headers.forEach (function(val, key) {
              if (!key.startsWith('vb-')) {
                headers.append(key, val);
              };
            });
            headers.append('Authorization', `Bearer ${tokenInfo.token}`);
            const alteredRequest = new Request(request, {headers});
            return alteredRequest;
          }
          return request;
        });
      }
   }

    return InjectFATokenFetchPlugin;
});

5. Register Security Provider

Change the userConfig property in the /webApps/{name}/app-flow.json file to the following:

"userConfig": {
    "type": "resources/js/FusionEmbeddedWithNoUserSecurityProvider",
    "configuration": {},
    "embedding": "any"
  }