BlackBerry Spark Communications Services Guide

Getting Started with Web

This overview guides you through the steps that are required to integrate the BlackBerry Spark Communications Services SDK for JavaScript with your web application.

See the discussion of differences between the JavaScript and other editions of the SDK.

Prerequisites

The SDK requires a Web browser that offers at least the following features:

Your application must be served via HTTPS (and not HTTP) because the SDK uses browser features that are only available when the page is running in a secure context.

The following browsers are supported:

The following browsers are supported with caveats:

The Safari and Edge browsers are do not include the P-521 ECC algorithms in their native WebCrypto implementation. The missing functionality can be provided via a WebCrypto polyfill prior to loading the bbm_sdk_web.js script. However, the use of polyfill is not recommended. The WebCrypto object is globally accessible. Any polyfill used to enhance the WebCrypto interface can be interfered with by any malicious script that can gain access to your application. This can result in user keys being compromised.

The SDK can be run in a web worker in any supported browser as well as in Safari (Safari is subject to the same caveat as when not running in a web worker).

You can provide a WebCrypto getRandomValues() polyfill, but it will likely require that you pass a secure random number generator seed into the web worker from outside.

Cross-Origin Resource Sharing

Cross-Origin Resource Sharing (CORS) is a mechanism that allows web applications to securely access API resources served by different organizations. The BlackBerry Infrastructure and your users' web browsers use this mechanism to determine who can use your application's domain via the SDK's APIs. This helps keep your application safe from cross-origin attacks on the web.

If your application has web endpoints, you must tell the BlackBerry Infrastructure where you will serve your application. The BlackBerry Infrastructure will then tell your users' web browsers that same information in API responses so that the browsers can enforce the CORS rules securely. Your application domain must be configured with an HTTP Access-Control-Allow-Origin header value that will be returned in all API responses. This value must contain your application's Origin, which is the scheme, host, and any non-default port that your application is served from.

For example, if your application is served from the URL https://example.com/application, then your application's Origin is https://example.com.

To configure your domain for CORS, select your application from the BlackBerry Online Account application list, select the Communications Services tab, and click on Edit. Enter your application's Origin value in the Allowed Origin field.

Configure Allowed Origin

You can configure a value of * to allow your domain to be accessed from any web site or web application. This can be useful when developing and testing your application in the sandbox. However, BlackBerry recommends configuring a full Allowed Origin value even for sandbox domains because it is more secure.

Content Security Policy

If you are using a Content-Security-Policy (CSP) HTTPS header when serving your application, you will need to include at least the policies shown below. You will likely also include other policies in this header to allow your application to access other services such as an identity provider and user management.

To ensure that the SDK can connect to the BlackBerry Infrastructure using the HTTPS and WSS protocols, your Content Security Policy must include:

connect-src https://*.bbmenterprise.com wss://*.bbmenterprise.com

Content Security Policy for WebAssembly

When configured to use the BlackBerry Key Management Service, the SDK for JavaScript uses a WebAssembly module to implement Argon2id key derivation. If your web application is served with the Content-Security-Policy header, you might need to work around inconsistencies in how current browsers consider WebAssembly against this header's policies. Specifically, you might need to specify script-src 'unsafe-eval'. Please refer to the documented behavior of current implementations for details on WebAssembly interactions with Content-Security-Policy in current browsers.

By default, the SDK will load the WebAssembly module needed to perform the Argon2id key derivation from argon2.wasm located alongside your Web application. In order for the SDK to be able to load this file, you must include a connect-src policy allowing the file to be loaded. For example, either of the following two policies will allow the SDK to load the WebAssembly module:

Add the SDK to your Application

  1. Download & Configure the latest version of the SDK for JavaScript.

  2. Copy sdk/bbm_sdk_web.js to a location accessible by your Web application.
  3. If your application is going to use the BlackBerry Key Management Service, you must also copy the sdk/argon2.wasm file to be in the same directory as the HTML page that loads the SDK.

  4. Import the SDK into your Web application by including the bbm_sdk_web.js script in your application's HTML file.

    <script src="path/to/bbm_sdk_web.js"></script>
    

    This provides access to the global BBMEnterprise object, which can be used to access the SDK functionality.

Authentication

Your application is responsible for providing access tokens to the SDK with the BBMEnterprise.authTokenCallback APIs. These tokens are used to identify, authenticate, and authorize your users.

As described in the Identity Providers guide, you can configure your domain in the sandbox to have user authentication disabled. Your application must still provide tokens using the BBMEnterprise.authTokenCallback APIs, but instead of getting them from a real identity provider, your application generates its own unsigned JWT tokens.

By default, all examples expect your domain to have user authentication disabled. Some examples may optionally be configured to use Google Sign-In or Azure Active Directory as an identity provider.

Key Management

By default, all examples use the BlackBerry Key Management Service which provides automatic management and synchronization of keys. The Support library comes with code that you can use for using Cloud Key Storage with Google Firebase or Azure Cosmos DB.

Start the SDK

In your application, create a new BBMEnterprise object as shown in the example below.

// Create the MockAuthManager that will generate unsigned JWT tokens for our
// sandbox domain that has user authentication disabled.  This example only
// returns a fixed user ID.  A real application would determine the user ID
// through user interaction or other means.
const mockAuthManager = new MockAuthManager();
mockAuthManager.getUserId = () => Promise.resolve('user1');

// Immediately invoke that getUserId() function and resolve its promise.
const localUserInfo = await mockAuthManager.authenticate();

// Initialize the SDK.
const sdk = new BBMEnterprise({
  // The domain that was provided to you when you registered to use the SDK.
  // This will be of the form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX. where each
  // X is a lowercase character or number.
  domain: 'domain',

  // It is recommended that you do your development and integration testing in
  // the sandbox environment.
  environment: 'Sandbox',

  // The user ID of the identity that is using the SDK.  In this example, it
  // comes from the localUserInfo returned by the MockAuthManager.
  userId: localUserInfo.userId,

  // This function is called when the SDK needs an access token.  Your
  // application must return a promise of the new access token.  In this
  // example, access tokens are supplied by the MockAuthManager.
  getToken: () => mockAuthManager.getBbmSdkToken(),

  // A description of the client. This will be used to describe this endpoint
  // when using endpoint management functionality. This should never be empty.
  // The description can be a maximum of 2000 Unicode Code Points.
  description: navigator.userAgent,

  // A friendly name in addition to the description. The nickname is optional
  // and should be set by a user, if desired.
  nickname: 'My web client',
});

BlackBerry Key Management Service

If your application is configured to use the BlackBerry Key Management Service, you must register listeners for the setupState and setupError events and then call setupStart() to begin endpoint setup.

The following code shows how to handle these events.

// Register to handle the setupState events.
sdk.on('setupState', async (state) => {
  try {
    switch (state.value) {
    case BBMEnterprise.SetupState.Success:
      // Setup succeeded!  Your application can now begin using the Messenger
      // and Media interfaces.
      break;

    case BBMEnterprise.SetupState.SyncRequired: {
      // The user's keys are ready to be synced with KMS.  The syncPasscodeState
      // indicates whether or not the user has existing keys.
      switch (sdk.syncPasscodeState) {
      case BBMEnterprise.SyncPasscodeState.New:
        // The user does not have any keys stored in KMS.  New keys will be
        // created for them using the passcode entered by the user.
        sdk.syncStart(await getPasscode(), BBMEnterprise.SyncStartAction.New);
        break;

      case BBMEnterprise.SyncPasscodeState.Existing:
        // The user has existing keys stored in KMS.  To use the existing keys,
        // start the sync with 'Existing'.  To create new keys for the user,
        // start the sync with 'New'.
        sdk.syncStart(
          await getPasscode(), BBMEnterprise.SyncStartAction.Existing);
        break;
      }
      break;
    }

    case BBMEnterprise.SetupState.SyncStarted:
      // Syncing of the keys from KMS has started.  If syncing fails, the
      // setupState will revert to 'SyncRequired' to allow your application to
      // try a new passcode or generate new keys.
      //
      // This state allows your application to track if an attempt to sync the
      // keys has been made or not.
      break;
    }
  }
  // Handle getPasscode() promise rejections.
  catch(error)
  {
    // Handle the error appropriately.
    console.error(`Endpoint setup failed: ${error}`);
  }
});

// Register to handle setupError events.
sdk.on('setupError', error => {
  console.log(`Endpoint setup failed: ${error.value}`);
});

// Start the SDK.
sdk.setupStart();

Cloud Key Storage

If your application is configured to use Cloud Key Storage, you must start the SDK differently.

You must define the getKeyProvider() function as a property of the BBMEnterprise configuration constructor argument. You must write this function.

  // If your application uses Cloud Key Storage, you must define this function.
  getKeyProvider: function() {
    // You must return a promise that will resolve to an implementation of
    // BBMEnterprise.KeyProviderInterface.
    return Promise.reject(new Error('You must implement getKeyProvider().'));
  }

You must call setup() to begin endpoint setup.

// Start the SDK.
sdk.setup()
.then(() => {
  // Setup succeeded!  Your application can now begin using the Messenger
  // and Media interfaces.
})
.catch(error => {
  console.log(`Endpoint setup failed: ${error}`);
});

Exploring the Examples

The SDK for JavaScript has example applications that are web applications that need to be served by a web server as standard HTML, JavaScript, CSS, and image files with the correct MIME types.

The simplest configuration is to simply have your web server serve the entire content of the expanded SDK archive, including the sdk and examples directories. The example applications expect those two directories to be siblings in the served content.

To use the examples that do not come in the SDK package, clone them from GitHub and add a symlink to the support directory that comes in the SDK's examples directory. This will allow these examples to find both the Support library and the SDK itself within the served content.

cd blackberry-spark-communications-services-sdk-web-*
git clone https://github.com/blackberry/BlackBerry-Communication-Services-Examples.git github-examples
ln -s ../examples/support github-examples/javascript/support

The README files that come with each of the web example applications explain how to configure and run them.