Skip to content

Commit 1253482

Browse files
authored
SDKS-4549: Update Protect Callback With New Signals SDK Config (#581)
* fix(ping-protect): update protect callback with new config * fix(ping-protect): handle behavioralDataCollection as string value * fix: update signal SDK; generate changeset; * fix: remove duplicate copyright block * fix: use resumeBehavioralData wrapper internally
1 parent 3b8616a commit 1253482

File tree

7 files changed

+16663
-19916
lines changed

7 files changed

+16663
-19916
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@forgerock/javascript-sdk': minor
3+
'@forgerock/ping-protect': minor
4+
---
5+
6+
fix(protect): update Protect callback with new Signals SDK config

packages/javascript-sdk/src/fr-auth/callbacks/ping-protect-initialize-callback.test.ts

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* ping-protect-intitialize-callback.test.ts
55
*
6-
* Copyright (c) 2024 - 2025 Ping Identity Corporation. All rights reserved.
6+
* Copyright (c) 2024 - 2026 Ping Identity Corporation. All rights reserved.
77
* This software may be modified and distributed under the terms
88
* of the MIT license. See the LICENSE file for details.
99
*/
@@ -186,6 +186,80 @@ describe('PingOneProtectInitializeCallback', () => {
186186
});
187187
});
188188

189+
it('should return signalsInitializationOptions directly when valid', () => {
190+
const signalsInitializationOptions = {
191+
agentIdentification: 'false',
192+
htmlGeoLocation: 'true',
193+
behavioralDataCollection: 'true',
194+
universalDeviceIdentification: 'false',
195+
option1: 'value1',
196+
disableTags: 'false',
197+
};
198+
199+
const callback = new PingOneProtectInitializeCallback({
200+
type: 'PingOneProtectInitializeCallback' as CallbackType,
201+
input: [],
202+
output: [
203+
{
204+
name: 'signalsInitializationOptions',
205+
value: signalsInitializationOptions,
206+
},
207+
{
208+
name: 'envId',
209+
value: 'legacy-env-id-that-should-be-ignored',
210+
},
211+
],
212+
});
213+
214+
const config = callback.getConfig();
215+
expect(config).toEqual(signalsInitializationOptions);
216+
expect(config).not.toHaveProperty('envId');
217+
});
218+
219+
it('should fallback to legacy config when signalsInitializationOptions is invalid', () => {
220+
const callback = new PingOneProtectInitializeCallback({
221+
type: 'PingOneProtectInitializeCallback' as CallbackType,
222+
input: [],
223+
output: [
224+
{
225+
name: 'signalsInitializationOptions',
226+
value: [],
227+
},
228+
{
229+
name: 'envId',
230+
value: '02fb4743-189a-4bc7-9d6c-a919edfe6447',
231+
},
232+
],
233+
});
234+
235+
const config = callback.getConfig();
236+
expect(config).toMatchObject({
237+
envId: '02fb4743-189a-4bc7-9d6c-a919edfe6447',
238+
behavioralDataCollection: true,
239+
disableTags: false,
240+
});
241+
});
242+
243+
it('should fallback to legacy config when signalsInitializationOptions is missing', () => {
244+
const callback = new PingOneProtectInitializeCallback({
245+
type: 'PingOneProtectInitializeCallback' as CallbackType,
246+
input: [],
247+
output: [
248+
{
249+
name: 'envId',
250+
value: '02fb4743-189a-4bc7-9d6c-a919edfe6447',
251+
},
252+
],
253+
});
254+
255+
const config = callback.getConfig();
256+
expect(config).toMatchObject({
257+
envId: '02fb4743-189a-4bc7-9d6c-a919edfe6447',
258+
behavioralDataCollection: true,
259+
disableTags: false,
260+
});
261+
});
262+
189263
it('should test the setClientError method', () => {
190264
const callback = new PingOneProtectInitializeCallback({
191265
type: 'PingOneProtectInitializeCallback' as CallbackType,

packages/javascript-sdk/src/fr-auth/callbacks/ping-protect-initialize-callback.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* ping-protect-initialize-callback.ts
55
*
6-
* Copyright (c) 2024 - 2025 Ping Identity Corporation. All rights reserved.
6+
* Copyright (c) 2024 - 2026 Ping Identity Corporation. All rights reserved.
77
* This software may be modified and distributed under the terms
88
* of the MIT license. See the LICENSE file for details.
99
*/
@@ -26,6 +26,18 @@ class PingOneProtectInitializeCallback extends FRCallback {
2626
* Get callback's initialization config settings
2727
*/
2828
public getConfig() {
29+
const signalsInitializationOptions = this.getOutputByName<Record<string, unknown> | undefined>(
30+
'signalsInitializationOptions',
31+
undefined,
32+
);
33+
if (
34+
signalsInitializationOptions !== null &&
35+
typeof signalsInitializationOptions === 'object' &&
36+
!Array.isArray(signalsInitializationOptions)
37+
) {
38+
return signalsInitializationOptions;
39+
}
40+
2941
const agentIdentification = this.getOutputByName<boolean | undefined>(
3042
'agentIdentification',
3143
undefined,

packages/ping-protect/src/lib/ping-protect.test.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
*
3-
* Copyright (c) 2024 - 2025 Ping Identity Corporation. All right reserved.
3+
* Copyright (c) 2024 - 2026 Ping Identity Corporation. All right reserved.
44
*
55
* This software may be modified and distributed under the terms
66
* of the MIT license. See the LICENSE file for details.
@@ -41,6 +41,22 @@ describe('PIProtect', () => {
4141
await PIProtect.start(config);
4242
expect(protectMock).toHaveBeenCalledWith(config);
4343
});
44+
it('should resume behavioralData when behavioralDataCollection is string true', async () => {
45+
await PIProtect.start({ envId: '12345', behavioralDataCollection: false });
46+
const resumeSpy = vi.spyOn(window._pingOneSignals, 'resumeBehavioralData');
47+
48+
await PIProtect.start({ envId: '12345', behavioralDataCollection: 'true' });
49+
50+
expect(resumeSpy).toHaveBeenCalledTimes(1);
51+
});
52+
it('should not resume behavioralData when behavioralDataCollection is string false', async () => {
53+
await PIProtect.start({ envId: '12345', behavioralDataCollection: false });
54+
const resumeSpy = vi.spyOn(window._pingOneSignals, 'resumeBehavioralData');
55+
56+
await PIProtect.start({ envId: '12345', behavioralDataCollection: 'false' });
57+
58+
expect(resumeSpy).not.toHaveBeenCalled();
59+
});
4460
it('should call pause behavioralData', () => {
4561
const protectMock = vi.spyOn(PIProtect, 'pauseBehavioralData');
4662
PIProtect.pauseBehavioralData();

packages/ping-protect/src/lib/ping-protect.ts

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
*
3-
* Copyright (c) 2024 - 2025 Ping Identity Corporation. All right reserved.
3+
* Copyright (c) 2024 - 2026 Ping Identity Corporation. All right reserved.
44
*
55
* This software may be modified and distributed under the terms
66
* of the MIT license. See the LICENSE file for details.
@@ -15,13 +15,20 @@ import {
1515
PingOneProtectEvaluationCallback,
1616
PingOneProtectInitializeCallback,
1717
} from '@forgerock/javascript-sdk';
18-
import { ProtectEvaluationConfig, ProtectInitializeConfig } from './ping-protect.types';
18+
import {
19+
ProtectEvaluationConfig,
20+
ProtectInitializeConfig,
21+
ProtectNodeInitializeConfig,
22+
SignalsInitializationOptions,
23+
} from './ping-protect.types';
1924

2025
export interface Identifiers {
2126
[key: string]: string;
2227
}
2328

24-
export type InitParams = Omit<ProtectInitializeConfig, '_type' | '_action'>;
29+
export type InitParams =
30+
| Omit<ProtectInitializeConfig, '_type' | '_action'>
31+
| SignalsInitializationOptions;
2532

2633
// Add Signals SDK namespace to the window object
2734
declare global {
@@ -69,8 +76,8 @@ export abstract class PIProtect {
6976
}
7077
await window._pingOneSignals.init(options);
7178

72-
if (options.behavioralDataCollection === true) {
73-
window._pingOneSignals.resumeBehavioralData();
79+
if (options.behavioralDataCollection === true || options.behavioralDataCollection === 'true') {
80+
PIProtect.resumeBehavioralData();
7481
}
7582
}
7683

@@ -137,14 +144,14 @@ export abstract class PIProtect {
137144
}
138145
}
139146

140-
public static getNodeConfig(step: FRStep): ProtectInitializeConfig | undefined {
147+
public static getNodeConfig(step: FRStep): ProtectNodeInitializeConfig | undefined {
141148
// Check for native callback first
142149
try {
143150
const nativeCallback = step.getCallbackOfType<PingOneProtectInitializeCallback>(
144151
CallbackType.PingOneProtectInitializeCallback,
145152
);
146153

147-
const config = nativeCallback?.getConfig() as ProtectInitializeConfig;
154+
const config = nativeCallback?.getConfig() as ProtectNodeInitializeConfig;
148155
return config;
149156
} catch (err) {
150157
// Do nothing

packages/ping-protect/src/lib/ping-protect.types.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
*
3-
* Copyright (c) 2024 - 2025 Ping Identity Corporation. All right reserved.
3+
* Copyright (c) 2024 - 2026 Ping Identity Corporation. All right reserved.
44
*
55
* This software may be modified and distributed under the terms
66
* of the MIT license. See the LICENSE file for details.
@@ -33,6 +33,9 @@ export interface ProtectInitializeConfig {
3333
waitForWindowLoad?: boolean;
3434
}
3535

36+
export type SignalsInitializationOptions = Record<string, unknown>;
37+
export type ProtectNodeInitializeConfig = ProtectInitializeConfig | SignalsInitializationOptions;
38+
3639
export interface ProtectEvaluationConfig {
3740
_type: 'PingOneProtect';
3841
_action: 'protect_risk_evaluation';

0 commit comments

Comments
 (0)