Orchestration SDKs

Step 2. Integrating PingOne Protect DaVinci flows in JavaScript

PingOne JavaScript

Integrating your application with PingOne Protect enables you to perform risk evaluations during your customer’s authentication flow.

Initialize data collection

The earlier you can initialize data collection, the more data it can collect to make a risk evaluation.

Your client application can manually initialize data collection, and must provide the configuration to control the PingOne Signals SDK.

There are two main methods for initializing data collection in a JavaScript app:

Direct initialization using the Protect interface

The DaVinci Client allows you to initialize data collection directly using the Protect interface. This provides maximum flexibility in how the collection operates.

To directly initialize data collection using the Protect interface, complete these steps:

  1. Add a configuration object to your code that defines the property values for data collection.

    The available properties are as follows:

    Parameter Description

    envID

    Required. Your PingOne environment identifier.

    For example, 3072206d-c6ce-ch15-m0nd-f87e972c7cc3

    deviceAttributesToIgnore

    Optional. A list of device attributes to ignore when collecting device signals.

    For example, AUDIO_OUTPUT_DEVICES or IS_ACCEPT_COOKIES.

    behavioralDataCollection

    When true, collect behavioral data.

    Default is true.

    hubUrl

    Optional. The iframe URL to use for cross-storage device IDs.

    disableHub

    When true, the client stores device data in the browser’s localStorage only.

    When false the client uses an iframe.

    Default is false.

    disableTags

    When true, the client does not collect tag data.

    Tags are used to record the pages the user visited, forming a browsing history.

    Default is false.

    externalIdentifiers

    Optional. A list of custom identifiers that are associated with the device entity in PingOne Protect.

    waitForWindowLoad

    When true, initialize the SDK on the load event, instead of the DOMContentLoaded event.

    Default is true.

    universalDeviceIdentification

    Optional. When true, device data in the payload returned to the server is provided as a signed JWT.

    agentIdentification

    Set to true when using risk policies that contain the PingID Device Trust predictor.

    Default is false.

    agentTimeout

    If you have enabled agentIdentification, use agentTimeout to specify a connection timeout, in milliseconds.

    Specifying a value overrides the default.

    Default is 1000.

    agentPort

    If you have enabled agentIdentification, use agentPort to specify the port for connecting to the trust agent.

    Specifying a value overrides the default.

    Default is 9400.

    Example code:

    const protectApi = protect({
        behavioralDataCollection: true,
        envId: "3072206d-c6ce-ch15-m0nd-f87e972c7cc3",
        deviceAttributesToIgnore: ['deviceId', 'serialNumber'],
    });
  2. Call an initialize function to start the data collection using the configuration object:

    await protectApi.start();
    
    console.log('Protect data collection initialized.');

On-demand initialization on receipt of ProtectCollector

You can choose not to initialize data collection on app startup and instead initialize it on-demand, when your DaVinci flow reaches the relevant node.

The collector received from the server contains the PingOne Protect configuration for initialization, meaning you can alter the options on the server without rebuilding your client apps:

Use the collector.output.config object to obtain the properties for initializing data collection as configured by the DaVinci flow.

JavaScript example of on-demand initialization
const collectors = davinciClient.getCollectors();
collectors.forEach((collector) => {
  if (collector.type === 'ProtectCollector') {
    // Retrieve Protect configuration from the server
    const config = collector.output.config;

    // Create Protect config, using some values obtained from server
    const protectApi = protect({
      envId: '3072206d-c6ce-ch15-m0nd-f87e972c7cc3',
      behavioralDataCollection: config.behavioralDataCollection,
      universalDeviceIdentification: config.universalDeviceIdentification,
    });

    // Initialize the Protect module and begin collecting data
    await protectApi.start();
  }
});

Pause and resume behavioral data capture

Part of the data collection includes collecting behavioral data, such as how the user interacts with the app, to help when performing evaluations.

There are scenarios where you might want to pause the collection of behavioral data:

  • To reduce memory and processor utilization. Continuously collecting behavioral data beyond authentication could reduce the performance of your client app.

  • You only want to consider device attribute data when performing PingOne Protect evaluations.

You can pause, and also resume behavioral data collection if required.

The SDKs provide the pauseBehavioralData() and resumeBehavioralData() methods for manually pausing and resuming the capture of behavioral data:

protectApi.pauseBehavioralData() // Pause data collection.
protectApi.resumeBehavioralData() // Resume data collection.

Return captured data to a DaVinci flow

To perform risk evaluations, the PingOne server requires the captured data.

On receipt of ProtectCollector, use the getData() method to prepare the collected data, and call the update() method populate the response with that captured data.

When the data is successfully collected, call next() to submit the data back to the server for evaluation.

async function onSubmitHandler() {
  try {
    const protectCollector = collectors.find((collector) => collector.type === 'ProtectCollector');

    // Update the Protect collector with the data collected
    if (protectCollector) {
      const updater = davinciClient.update(protectCollector);
      const data = await protectApi.getData();
      updater(data);
    }

    // Submit all collectors and get the next node in the flow
    await davinciClient.next();
  } catch (err) {
    // handle error
  }
}