Step 3. Develop the client app
Integrating your application with PingOne Protect enables you to perform risk evaluations during your customer’s journey.
Add code for the following tasks to fully integrate with PingOne Protect:
Initialize data collection
You must initialize the PingOne Signals SDK so that it collects the data needed to evaluate risk.
The earlier you can initialize the PingOne Signals SDK, the more data it can collect to make a risk evaluation.
You can initialize the PingOne Signals SDK by using the start()
method, which supports the following parameters:
Parameter |
Description |
||
Android |
iOS |
JavaScript |
|
|
Required. Your PingOne environment identifier. |
||
|
Optional. A list of device attributes to ignore when collecting device signals. For example, |
||
|
|
When Default is |
|
|
|
When Default is |
|
|
|
When Default is |
|
N/A |
|
Number of days that device attestation can rely upon the device fallback key. Default: |
|
N/A |
|
When When Default is |
|
N/A |
|
When Tags are used to record the pages the user visited, forming a browsing history. Default is |
|
N/A |
|
When Default is |
|
N/A |
|
Optional. A list of custom identifiers that are associated with the device entity in PingOne Protect. |
|
N/A |
|
Optional. The iframe URL to use for cross-storage device IDs. |
|
N/A |
|
When Default is |
There are two options for initializing the PingOne Signals SDK:
Initialize manually
Call the start()
method before users start interacting with your application to gather the most data and make the most informed risk evaluations.
Pass in the configuration parameters as required.
try {
val params =
PIInitParams(
envId = "3072206d-c6ce-4c19-a366-f87e972c7cc3",
)
PIProtect.start(context, params)
Logger.info("Settings Protect", "Initialize succeeded")
} catch (e: Exception) {
Logger.error("Initialize Error", e.message)
throw e
}
let initParams = PIInitParams(envId: "3072206d-c6ce-4c19-a366-f87e972c7cc3")
PIProtect.start(initParams: initParams) { error in
if let error = error as? NSError {
FRLog.e("Initialize error: \(error.localizedDescription)")
} else {
FRLog.i("Initialize succeeded")
}
}
import { PIProtect } from '@forgerock/ping-protect';
try {
// Initialize PingOne Protect with manual configuration
PIProtect.start({ envId: '3072206d-c6ce-4c19-a366-f87e972c7cc3' });
} catch (err) {
console.error(err);
}
Initialize based on a callback
Not all authentication journeys perform risk evaluations, and therefore do not need to initialize data collection. You can choose to initialize capture of data on receipt of the PingOneProtectInitializeCallback
callback rather than during app start up.
The callback also provides the configuration parameters.
try {
val callback =
node.getCallback(PingOneProtectInitializeCallback::class.java)
callback.start(context)
} catch (e: PingOneProtectInitException) {
Logger.error("PingOneInitException", e, e.message)
} catch (e: Exception) {
Logger.error("PingOneInitException", e, e.message)
callback.setClientError(e.message);
}
node.next()
if callback.type == "PingOneProtectInitializeCallback",
let pingOneProtectInitCallback = callback as? PingOneProtectInitializeCallback
{
pingOneProtectInitCallback.start { result in
DispatchQueue.main.async {
var initResult = ""
switch result {
case .success:
initResult = "Success"
case .failure(let error):
initResult = "Error: \(error.localizedDescription)"
}
FRLog.i("PingOne Protect Initialize Result: \n\(initResult)")
handleNode(node)
}
}
return
}
import { PIProtect } from '@forgerock/ping-protect';
if (step.getCallbacksOfType('PingOneProtectInitializeCallback')) {
const callback = step.getCallbackOfType('PingOneProtectInitializeCallback');
// Obtain config properties from the callback
const config = callback.getConfig();
console.log(JSON.stringify(config));
try {
// Initialize PingOne Protect with configuration from callback
await PIProtect.start(config);
} catch (err) {
// Add any errors to the callback
callback.setClientError(err.message);
}
}
FRAuth.next(step);
Pause and resume behavioral data capture
The PingOne Protect Signals SDK can capture 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. For example, the user might not be interacting with the app, or you only want to use device attribute data to be considered when performing PingOne Protect evaluations. You can then resume behavioral data collection when required.
The SDKs provide the pauseBehavioralData()
and resumeBehavioralData()
methods for pausing and resuming the capture of behavioral data.
The PingOneProtectEvaluationCallback
callback can include a flag to pause or resume behavioral capture that you should respond to as follows:
val callback =
node.getCallback(PingOneProtectEvaluationCallback::class.java)
const shouldPause = callback.pauseBehavioralData
Logger.info("PingOneProtectEvaluationCallback", "getPauseBehavioralData: ${shouldPause}")
if (shouldPause) {
PIProtect.pauseBehavioralData()
}
if callback.type == "PingOneProtectEvaluationCallback",
let pingOneProtectEvaluationCallback = callback as? PingOneProtectEvaluationCallback
{
if let shouldPause = pingOneProtectEvaluationCallback.pauseBehavioralData, shouldPause {
PIProtect.pauseBehavioralData()
}
}
const callback = step.getCallbackOfType('PingOneProtectEvaluationCallback');
const shouldPause = callback.getPauseBehavioralData();
console.log(`getPauseBehavioralData: ${shouldPause}`);
if (shouldPause) {
PIProtect.pauseBehavioralData();
}
Return collected data for a risk evaluation
To perform risk evaluations, the PingOne server requires the captured data.
On receipt of a PingOneProtectEvaluationCallback
callback, use the getData()
method to populate the response with the captured data.
try {
val callback =
node.getCallback(PingOneProtectEvaluationCallback::class.java)
callback.getData(context)
} catch (e: PingOneProtectEvaluationException) {
Logger.error("PingOneRiskEvaluationCallback", e, e.message)
} catch (e: Exception) {
Logger.error("PingOneRiskEvaluationCallback", e, e.message)
}
if callback.type == "PingOneProtectEvaluationCallback",
let pingOneProtectEvaluationCallback = callback as? PingOneProtectEvaluationCallback
{
pingOneProtectEvaluationCallback.getData { result in
DispatchQueue.main.async {
var evaluationResult = ""
switch result {
case .success:
evaluationResult = "Success"
case .failure(let error):
evaluationResult = "Error: \(error.localizedDescription)"
}
FRLog.i("PingOne Protect Evaluation Result: \n\(evaluationResult)")
handleNode(node)
}
}
return
}
let data;
if (step.getCallbacksOfType('PingOneProtectEvaluationCallback')) {
const callback = step.getCallbackOfType('PingOneProtectEvaluationCallback');
try {
// Asynchronous call
data = await PIProtect.getData();
} catch (err) {
// Add any errors to the callback
callback.setClientError(err.message);
}
}
callback.setData(data);
FRAuth.next(step);