Skip to content

Commit a3494b9

Browse files
committed
feat: support-metadata-marketplace-protect
add marketplace node support to the ping protect module
1 parent 221818e commit a3494b9

File tree

20 files changed

+945
-26
lines changed

20 files changed

+945
-26
lines changed

e2e/autoscript-apps/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
<a href="./src/authn-second-factor/index.html">AuthN: Second Factor</a><br />
3838
<a href="./src/authn-saml/index.html">AuthN: SAML</a><br />
3939
<a href="./src/authn-social-login-am/index.html">AuthN: Social Login AM</a><br />
40+
<a href="./src/authn-protect-metadata/index.html">AuthN: Protect Metadata AM</a><br />
4041
<a href="./src/authn-social-login-idm/index.html">AuthN: Social Login IDM</a><br />
4142
<a href="./src/authn-webauthn/index.html">AuthN: WebAuthn</a><br />
4243
<a href="./src/authn-webauthn-device-registration/index.html">
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/*
2+
* @forgerock/javascript-sdk
3+
*
4+
* autoscript.ts
5+
*
6+
* Copyright (c) 2024 ForgeRock. All rights reserved.
7+
* This software may be modified and distributed under the terms
8+
* of the MIT license. See the LICENSE file for details.
9+
*/
10+
// @ts-nocheck
11+
import * as forgerock from '@forgerock/javascript-sdk';
12+
import { PIProtect } from '@forgerock/ping-protect';
13+
import { delay as rxDelay, map, mergeMap } from 'rxjs/operators';
14+
import { from } from 'rxjs';
15+
16+
function autoscript() {
17+
const delay = 0;
18+
19+
const url = new URL(window.location.href);
20+
const amUrl = url.searchParams.get('amUrl') || 'http://localhost:9443/am';
21+
const realmPath = url.searchParams.get('realmPath') || 'root';
22+
const un = url.searchParams.get('un') || 'sdkuser';
23+
const pw = url.searchParams.get('pw') || 'password';
24+
const pauseBehaviorData = url.searchParams.get('pauseBehaviorData') || 'true';
25+
const tree = url.searchParams.get('tree') || 'TEST_MetadataMarketPlace';
26+
27+
console.log('Configure the SDK');
28+
forgerock.Config.set({
29+
realmPath,
30+
tree,
31+
serverConfig: {
32+
baseUrl: amUrl,
33+
},
34+
});
35+
36+
try {
37+
forgerock.SessionManager.logout();
38+
} catch (err) {
39+
// Do nothing
40+
}
41+
42+
console.log('Initiate first step with `undefined`');
43+
// Wrapping in setTimeout to give the test time to bind listener to console.log
44+
setTimeout(function () {
45+
from(forgerock.FRAuth.start())
46+
.pipe(
47+
mergeMap(
48+
(step) => {
49+
try {
50+
const config = PIProtect.getNodeConfig(step);
51+
52+
console.log('start protect');
53+
return PIProtect.start(config);
54+
} catch (err) {
55+
const cb = (step as forgerock.Step).getCallbackOfType(
56+
'MetadataCallback',
57+
) as forgerock.MetadataCallback;
58+
59+
clientError.setInputValue('we had a failure');
60+
}
61+
},
62+
(step) => {
63+
return step;
64+
},
65+
),
66+
mergeMap((step) => {
67+
console.log('Submitting ping protect start');
68+
return forgerock.FRAuth.next(step);
69+
}),
70+
rxDelay(delay),
71+
72+
mergeMap(async (step) => {
73+
try {
74+
const data = await PIProtect.getData();
75+
76+
PIProtect.setNodeInputValue(step, data);
77+
console.log('Submitting ping protect evaluation');
78+
return forgerock.FRAuth.next(step);
79+
} catch (err) {
80+
return err;
81+
}
82+
}),
83+
map((step) => {
84+
if (step.payload.status === 401) {
85+
throw new Error('Auth_Error');
86+
} else if (step.payload.tokenId) {
87+
console.log('Basic login with Protect successful');
88+
document.body.innerHTML = '<p class="Logged_In">Login successful</p>';
89+
} else {
90+
throw new Error('Something went wrong.');
91+
}
92+
}),
93+
)
94+
.subscribe({
95+
error: (err) => {
96+
console.log(`Error: ${err.message}`);
97+
document.body.innerHTML = `<p class="Test_Complete">${err.message}</p>`;
98+
},
99+
complete: () => {
100+
console.log('Test script complete');
101+
document.body.innerHTML = `<p class="Test_Complete">Test script complete</p>`;
102+
},
103+
});
104+
}, 250);
105+
}
106+
autoscript();
107+
108+
export default autoscript;
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<!doctype html>
2+
<html>
3+
<head>
4+
<title>E2E Test | ForgeRock JavaScript SDK</title>
5+
6+
<!-- Needed only for automation with mock server -->
7+
<meta name="referrer" content="unsafe-url" />
8+
9+
<link rel="shortcut icon" href="/fr-ico.png" type="image/png" />
10+
11+
<style>
12+
@media (prefers-color-scheme: dark) {
13+
html {
14+
background-color: black;
15+
color: white;
16+
}
17+
a {
18+
color: lightblue;
19+
}
20+
a:visited {
21+
color: lavender;
22+
}
23+
a:hover {
24+
color: lightskyblue;
25+
}
26+
}
27+
</style>
28+
</head>
29+
30+
<body>
31+
<script type="module" src="./autoscript.ts"></script>
32+
</body>
33+
</html>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* @forgerock/javascript-sdk
3+
*
4+
* authn-otp-reg.test.ts
5+
*
6+
* Copyright (c) 2024 ForgeRock. All rights reserved.
7+
* This software may be modified and distributed under the terms
8+
* of the MIT license. See the LICENSE file for details.
9+
*/
10+
import { test, expect } from '@playwright/test';
11+
import { setupAndGo } from '../utilities/setup-and-go';
12+
13+
test.describe('Login with marketplace nodes', () => {
14+
test(`Ping marketplace nodes`, async ({ page, browserName }) => {
15+
const { messageArray } = await setupAndGo(page, browserName, 'authn-protect-metadata/');
16+
17+
// Test assertions
18+
expect(messageArray.includes('Submitting ping protect start')).toBe(true);
19+
20+
expect(messageArray.includes('Submitting ping protect evaluation')).toBe(true);
21+
expect(messageArray.includes('Basic login with Protect successful')).toBe(true);
22+
});
23+
});

e2e/mock-api-v2/project.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@
2929
"development": {
3030
"watch": true
3131
},
32+
"example-server": {
33+
"main": "e2e/mock-api-v2/src/example-server.ts"
34+
},
3235
"production": {
3336
"esbuildOptions": {
3437
"sourcemap": false,
@@ -46,8 +49,8 @@
4649
"buildTarget": "e2e-mock-api-v2:build"
4750
},
4851
"configurations": {
49-
"development": {
50-
"buildTarget": "e2e-mock-api-v2:build:development"
52+
"example-server": {
53+
"buildTarget": "e2e-mock-api-v2:build:example-server"
5154
},
5255
"production": {
5356
"buildTarget": "e2e-mock-api-v2:build:production"
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { RouterBuilder, Middlewares, ExampleServer } from 'effect-http';
2+
import { NodeRuntime } from '@effect/platform-node';
3+
import { NodeServer } from 'effect-http-node';
4+
import { apiSpec } from './spec';
5+
6+
const app = ExampleServer.make(apiSpec).pipe(RouterBuilder.build, Middlewares.errorLog);
7+
8+
app.pipe(NodeServer.listen({ port: 9443 }), NodeRuntime.runMain);

e2e/mock-api/src/app/responses.js

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1119,6 +1119,111 @@ export const wellKnownPing = {
11191119
code_challenge_methods_supported: ['plain', 'S256'],
11201120
};
11211121

1122+
export const MetadataMarketPlaceInitialize = {
1123+
authId: 'foo',
1124+
callbacks: [
1125+
{
1126+
type: 'MetadataCallback',
1127+
output: [
1128+
{
1129+
name: 'data',
1130+
value: {
1131+
_type: 'PingOneProtect',
1132+
_action: 'protect_initialize',
1133+
envId: 'some_id',
1134+
consoleLogEnabled: true,
1135+
deviceAttributesToIgnore: [],
1136+
customHost: '',
1137+
lazyMetadata: true,
1138+
behavioralDataCollection: true,
1139+
disableHub: true,
1140+
deviceKeyRsyncIntervals: 10,
1141+
enableTrust: true,
1142+
disableTags: true,
1143+
},
1144+
},
1145+
],
1146+
},
1147+
{
1148+
type: 'HiddenValueCallback',
1149+
output: [
1150+
{
1151+
name: 'value',
1152+
value: '',
1153+
},
1154+
{
1155+
name: 'id',
1156+
value: 'clientError',
1157+
},
1158+
],
1159+
input: [
1160+
{
1161+
name: 'IDToken1',
1162+
value: '',
1163+
},
1164+
],
1165+
},
1166+
],
1167+
};
1168+
1169+
export const MetadataMarketPlacePingOneEvaluation = {
1170+
authId: 'foo',
1171+
callbacks: [
1172+
{
1173+
type: 'MetadataCallback',
1174+
output: [
1175+
{
1176+
name: 'data',
1177+
value: {
1178+
_type: 'PingOneProtect',
1179+
_action: 'protect_risk_evaluation',
1180+
envId: 'some_id',
1181+
pauseBehavioralData: true,
1182+
},
1183+
},
1184+
],
1185+
},
1186+
{
1187+
type: 'HiddenValueCallback',
1188+
output: [
1189+
{
1190+
name: 'value',
1191+
value: '',
1192+
},
1193+
{
1194+
name: 'id',
1195+
value: 'pingone_risk_evaluation_signals',
1196+
},
1197+
],
1198+
input: [
1199+
{
1200+
name: 'IDToken1',
1201+
value: 'pingone_risk_evaluation_signals',
1202+
},
1203+
],
1204+
},
1205+
{
1206+
type: 'HiddenValueCallback',
1207+
output: [
1208+
{
1209+
name: 'value',
1210+
value: '',
1211+
},
1212+
{
1213+
name: 'id',
1214+
value: 'clientError',
1215+
},
1216+
],
1217+
input: [
1218+
{
1219+
name: 'IDToken1',
1220+
value: '',
1221+
},
1222+
],
1223+
},
1224+
],
1225+
};
1226+
11221227
export const recaptchaEnterpriseCallback = {
11231228
authId: 'foo',
11241229
callbacks: [

e2e/mock-api/src/app/routes.auth.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import {
4646
wellKnownForgeRock,
4747
wellKnownPing,
4848
recaptchaEnterpriseCallback,
49+
MetadataMarketPlaceInitialize,
4950
} from './responses.js';
5051
import initialRegResponse from './response.registration.js';
5152
import wait from './wait.js';
@@ -87,6 +88,8 @@ export default function (app) {
8788
res.json(pingProtectInitialize);
8889
} else if (req.query.authIndexValue === 'IDMSocialLogin') {
8990
res.json(selectIdPCallback);
91+
} else if (req.query.authIndexValue === 'TEST_MetadataMarketPlace') {
92+
res.json(MetadataMarketPlaceInitialize);
9093
} else if (req.query.authIndexValue === 'AMSocialLogin') {
9194
res.json(idpChoiceCallback);
9295
} else if (req.query.authIndexValue === 'RecaptchaEnterprise') {
@@ -109,6 +112,7 @@ export default function (app) {
109112
}
110113
} else if (req.query.authIndexValue === 'LoginWithEmail') {
111114
res.json(emailSuspend);
115+
<<<<<<< HEAD
112116
} else if (req.query.authIndexValue === 'RecaptchaEnterprise') {
113117
console.log(req.body.callbacks);
114118
if (req.body.callbacks[0].type === 'NameCallback') {
@@ -132,6 +136,42 @@ export default function (app) {
132136
res.json(authSuccess);
133137
}
134138
}
139+
=======
140+
} else if (req.query.authIndexValue === 'TEST_MetadataMarketPlace') {
141+
if (req.body.callbacks.find((cb) => cb.type === 'MetadataCallback')) {
142+
const metadataCb = req.body.callbacks.find((cb) => cb.type === 'MetadataCallback');
143+
const action = metadataCb.output[0].value._action;
144+
console.log('the action', action);
145+
if (action === 'protect_initialize') {
146+
if (req.body.callbacks.find((cb) => cb.type === 'HiddenValueCallback')) {
147+
const hiddenCb = req.body.callbacks.find((cb) => cb.type === 'HiddenValueCallback');
148+
if (hiddenCb.input[0].value === 'we had an error') {
149+
return res.json(authFail);
150+
}
151+
return res.json(MetadataMarketPlacePingOneEvaluation);
152+
}
153+
}
154+
if (action === 'protect_risk_evaluation') {
155+
if (req.body.callbacks.find((cb) => cb.type === 'HiddenValueCallback')) {
156+
const hiddenCb = req.body.callbacks.find((cb) => cb.type === 'HiddenValueCallback');
157+
if (hiddenCb.input[0].value === 'we had an error') {
158+
return res.json(authFail);
159+
}
160+
return res.json(authSuccess);
161+
}
162+
}
163+
} else {
164+
if (req.body.callbacks.find((cb) => cb.type === 'PingOneEvaluationCallback')) {
165+
const cb = req.body.callbacks.find((cb) => cb.type === 'PingOneEvaluationCallback');
166+
if (cb.input[0].value === 'the value to set') {
167+
return res.json(authSuccess);
168+
} else {
169+
return res.json(authFail);
170+
}
171+
}
172+
}
173+
return res.json(MetadataMarketPlacePingOneEvaluation);
174+
>>>>>>> 0fab975 (feat: support-metadata-marketplace-protect)
135175
} else if (req.query.authIndexValue === 'QRCodeTest') {
136176
// If QR Code callbacks are being returned, return success
137177
if (req.body.callbacks.find((cb) => cb.type === 'HiddenValueCallback')) {

0 commit comments

Comments
 (0)