Getting Started with Node.js
This overview will guide you through the steps required to integrate the BlackBerry Spark Communications Services SDK for JavaScript into your Node.js application.
See the discussion of differences between the JavaScript and other editions of the SDK.
Prerequisites
The SDK for Node.js requires:
- Node.js version 6.0 or later (8.0 or later is recommended)
- A native compiler which can be run from node-gyp. Only installing the compiler needs to be done as per these instructions, the usage of node-gyp is handled within the SDK.
Content Security Policy
You can use the isomorphic SDK Node.js package to create a Web application.
If you are using a Content-Security-Policy
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:
connect-src 'self'
connect-src https://application.example.com/path/to/argon2.wasm
Add the SDK to your Application
- Download & Configure the latest version of the SDK for Node.js.
-
Initialize a directory structure for your Node.js application project by running:
npm init
Add the bbm-enterprise Node.js package as a dependency of your application by running:
npm install FILENAME --production
where FILENAME is the path to the file downloaded above.
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.
getToken()
function in the Start
the SDK section below creates these tokens.
Key Management
By default, all examples use the BlackBerry Key Management Service which provides automatic management and synchronization of keys.
Start the SDK
In your application, import the BBMEnterprise
module:
const BBMEnterprise = require('bbm-enterprise');
In your application, create a new BBMEnterprise
object as
shown in the example below.
// Load the crypto module that we will use when generating unsigned JWT tokens. const crypto = require('crypto'); // 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 // it is a fixed value. userId: 'user1', // 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: () => { // Because the Support library for JavaScript does not currently support // Node.js, we must generate these unsigned JWT tokens manually. const jti = BBMEnterprise.Util.base64urlEncode( new Uint8Array(crypto.randomBytes(20)) ).substring(0, 18); // The current time, in seconds. const now = (Date.now() / 1000) | 0; // Create the JWT header and body. const tokenHeader = BBMEnterprise.Util.base64urlEncode(JSON.stringify({ alg: 'none' })); const tokenBody = BBMEnterprise.Util.base64urlEncode(JSON.stringify({ jti: jti, sub: 'user1', // Valid since 60 seconds ago to avoid clock skew issues. iat: now - 60, // Expires in one day. exp: now + 86400 })); return Promise.resolve(`${tokenHeader}.${tokenBody}.`); }, // 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: 'node ' + process.version, // A friendly name in addition to the description. The nickname is optional // and should be set by a user, if desired. nickname: 'My node 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.
getPasscode()
that returns the passcode that protects the
user's keys.
// Register to handle the setupState events. sdk.on('setupState', (state) => { 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(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(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; } }); // 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}`); });