Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
6 changes: 4 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*/DS_Store
**/*.DS_Store
.pnpm-store/*

# Generated code
tmp/
e2e/**/dist
Expand Down Expand Up @@ -30,9 +31,10 @@ packages/javascript-sdk/lib/
.swc
.vite
.env.serve.development
package-lock.json

# Certificates
# *.pem
*.pem

# IDEs
.vscode
Expand Down Expand Up @@ -83,4 +85,4 @@ outputs/*

e2e/mock-api-v2/html/*

vitest.config.*.timestamp*
vitest.config.*.timestamp*
6 changes: 5 additions & 1 deletion e2e/autoscript-apps/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,18 @@
<a href="./src/authn-basic/index.html">AuthN: Basic</a><br />
<a href="./src/authn-basic-self-service/">AuthN: Self Service</a><br />
<a href="./src/authn-central-login/index.html">AuthN: Central Login</a><br />
<a href="./src/authn-central-login-no-iframe/index.html">AuthN: Central Login, no iframe</a
><br />
<a href="./src/authn-central-logout/index.html">AuthN: Central Logout Ping</a><br />
<a href="./src/authn-central-logout-wellknown/index.html"
>AuthN: Central Logout with Wellknown</a
><br />
<a href="./src/authn-device-profile/index.html">AuthN: Device Profile</a><br />
<a href="./src/authn-protect/index.html">AuthN: Ping Protect</a><br />
<a href="./src/authn-email-suspend/index.html">AuthN: Email Suspend</a><br />
<a href="./src/authn-recaptcha-enterprise/index.html">AuthN: Recaptcha Enterprise</a><br />
<a href="./src/authn-no-session/index.html">AuthN: No Session</a><br />
<a href="./src/authn-oauth/index.html">AuthN: OAuth</a><br />
<a href="./src/authn-wellknown/index.html">AuthN: WellKnown</a><br />
<a href="./src/authn-platform/index.html">AuthN: Platform Login</a><br />
<a href="./src/authn-second-factor/index.html">AuthN: Second Factor</a><br />
<a href="./src/authn-saml/index.html">AuthN: SAML</a><br />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* autoscript.ts
*
* Copyright (c) 2020 ForgeRock. All rights reserved.
* Copyright (c) 2020 - 2025 Ping Identity Corporation. All rights reserved.
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
Expand Down
2 changes: 1 addition & 1 deletion e2e/autoscript-apps/src/authn-basic/autoscript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* autoscript.ts
*
* Copyright (c) 2020 ForgeRock. All rights reserved.
* Copyright (c) 2020 - 2025 Ping Identity Corporation. All rights reserved.
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
Expand Down
145 changes: 145 additions & 0 deletions e2e/autoscript-apps/src/authn-central-login-no-iframe/autoscript.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
/*
* @forgerock/javascript-sdk
*
* autoscript.ts
*
* Copyright (c) 2020 - 2025 Ping Identity Corporation. All rights reserved.
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
// @ts-nocheck
import * as forgerock from '@forgerock/javascript-sdk';
import { delay as rxDelay, map, mergeMap } from 'rxjs/operators';
import { from } from 'rxjs';

function autoscript() {
const delay = 0;

const url = new URL(window.location.href);
const amUrl = url.searchParams.get('amUrl') || 'http://localhost:9443/am';
const preAuthenticated = url.searchParams.get('preAuthenticated') || 'false';
const code = url.searchParams.get('code') || '';
const clientId = url.searchParams.get('clientId');
const client_id = url.searchParams.get('client_id');
const error = url.searchParams.get('error_description') || false;
const realmPath = url.searchParams.get('realmPath') || 'root';
const scope = url.searchParams.get('scope') || 'openid profile me.read';
const state = url.searchParams.get('state') || '';
const acr_values = url.searchParams.get('acr') || 'skipBackgroundRequest';
// in central login we use an auth query param for the return of our mock 401 request
// this is to prevent the evaluation of the page before we have technically authenticated
const auth = url.searchParams.get('auth') || false;

let tokenStore = url.searchParams.get('tokenStore') || 'localStorage';

// Support full redirects by setting storage, rather than rely purely on URL
if (!localStorage.getItem('tokenStore')) {
localStorage.setItem('tokenStore', tokenStore);
} else {
tokenStore = localStorage.getItem('tokenStore');
}

console.log('Configure the SDK');
forgerock.Config.set({
clientId: clientId || client_id || 'CentralLoginOAuthClient',
realmPath,
redirectUri: `${url.origin}/src/${
preAuthenticated === 'false' ? 'authn-central-login' : '_callback'
}/`,
scope,
serverConfig: {
baseUrl: amUrl,
},
tokenStore,
});

if (!code && !state) {
try {
forgerock.SessionManager.logout();
} catch (err) {
// Do nothing
}
}

console.log('Initiate first step with `undefined`');

// Wrapping in setTimeout to give the test time to bind listener to console.log
setTimeout(() => {
from([1])
.pipe(
map(() => {
if (preAuthenticated === 'true') {
console.log('Set mock cookie to represent existing session');
document.cookie = 'iPlanetDirectoryPro=abcd1234; domain=localhost; path=/';
if (code && state) {
window.sessionStorage.setItem(
`FR-SDK-${clientId}`,
JSON.stringify({ responseType: 'code', state, verifier: '1234' }),
);
}
}
return;
}),
rxDelay(delay),
mergeMap((step) => {
let tokens;
// detect when in iframe, throw as error if so
if (window.self !== window.top) {
throw new Error('Loaded_In_Iframe');
} else if (code && state) {
tokens = forgerock.TokenManager.getTokens({
query: { code, state, acr_values },
});
} else {
tokens = forgerock.TokenManager.getTokens({
skipBackgroundRequest: true,
login: 'redirect',
query: { acr_values },
});
}
return tokens;
}),
map((tokens) => {
if (tokens.accessToken) {
console.log('OAuth authorization successful');
document.body.innerHTML = '<p class="Logged_In">Login successful</p>';
} else {
throw new Error('Session_Error');
}
}),
rxDelay(delay),
mergeMap(() => {
console.log('Remove cookie');
document.cookie = '';
console.log('Initiate logout');
return forgerock.FRUser.logout();
}),
)
.subscribe({
error: (err) => {
/*
* We added this because Playwright was too fast for the dom element.
* When we make a request to central login we have to force a 401 page to mimick the real life scenario of the page being requested
* If we do this, we append a query param of auth to make sure we don't complete the flow until we are redirected from that page
* By saying we have !auth query param value, we are essentially mimicking the idea that we are waiting for the central login redirect
* to complete the redirect.
*/
if (!auth) {
return;
}
console.log(`Error: ${err.message}`);
document.body.innerHTML = `<p class="Test_Complete">${err.message}</p>`;
localStorage.clear();
},
complete: () => {
console.log('Test script complete');
document.body.innerHTML = `<p class="Test_Complete">Test script complete</p>`;
history.replaceState(null, null, window.location.origin + window.location.pathname);
localStorage.clear();
},
});
}, 250);
}

autoscript();
export default autoscript;
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@
</head>

<body>
<!-- script src="/_polyfills/fast-text-encoder.js"></script -->

<script src="autoscript.ts" type="module"></script>
<script type="module" src="./autoscript.ts"></script>
</body>
</html>
88 changes: 50 additions & 38 deletions e2e/autoscript-apps/src/authn-central-login-wellknown/autoscript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* autoscript.ts
*
* Copyright (c) 2020 ForgeRock. All rights reserved.
* Copyright (c) 2020 - 2025 Ping Identity Corporation. All rights reserved.
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
Expand All @@ -16,49 +16,50 @@ async function autoscript() {
const delay = 0;

const url = new URL(window.location.href);
const preAuthenticated = url.searchParams.get('preAuthenticated') || 'false';
const code = url.searchParams.get('code') || '';
const error = url.searchParams.get('error') || '';
const clientId = url.searchParams.get('clientId');
const client_id = url.searchParams.get('client_id');
const error = url.searchParams.get('error_description') || false;
const realmPath = url.searchParams.get('realmPath') || 'root';
const scope = url.searchParams.get('scope') || 'openid profile me.read';
const state = url.searchParams.get('state') || '';
const acr_values = url.searchParams.get('acr') || 'SpecificTree';
// in central login we use an auth query param for the return of our mock 401 request
// this is to prevent the evaluation of the page before we have technically authenticated
const auth = url.searchParams.get('auth') || false;
const acr_values = url.searchParams.get('acr') || 'SpecificTree';
let wellknown =
url.searchParams.get('wellknown') || 'http://localhost:9443/am/.well-known/oidc-configuration';

let clientId = url.searchParams.get('clientId') || 'CentralLoginOAuthClient';
let realmPath = url.searchParams.get('realmPath') || 'root';
// The `revoke` scope is required for PingOne support
let scope = url.searchParams.get('scope') || 'openid profile me.read revoke';
let wellKnownUrl =
url.searchParams.get('wellKnownUrl') ||
'http://localhost:9443/am/.well-known/oidc-configuration';
let tokenStore = url.searchParams.get('tokenStore') || 'localStorage';

console.log('Configure the SDK');

if (wellKnownUrl) {
localStorage.setItem('wellknown', wellKnownUrl);
localStorage.setItem('clientId', clientId);
localStorage.setItem('realmPath', realmPath);
localStorage.setItem('scope', scope);
// Support full redirects by setting storage, rather than rely purely on URL
if (!localStorage.getItem('tokenStore')) {
localStorage.setItem('tokenStore', tokenStore);
} else {
wellKnownUrl = localStorage.getItem('wellknown');
clientId = localStorage.getItem('clientId');
realmPath = localStorage.getItem('realmPath');
scope = localStorage.getItem('scope');
tokenStore = localStorage.getItem('tokenStore');
}
await forgerock.Config.setAsync({
clientId,

console.log('Configure the SDK');
forgerock.Config.setAsync({
clientId: clientId || client_id || 'CentralLoginOAuthClient',
realmPath,
redirectUri: `${url.origin}/src/authn-central-login-wellknown/`,
redirectUri: `${url.origin}/src/${
preAuthenticated === 'false' ? 'authn-central-login' : '_callback'
}/`,
scope,
serverConfig: {
wellknown: wellKnownUrl,
wellknown,
},
tokenStore,
});

try {
forgerock.SessionManager.logout();
} catch (err) {
// Do nothing
if (!code && !state) {
try {
forgerock.SessionManager.logout();
} catch (err) {
// Do nothing
}
}

console.log('Initiate first step with `undefined`');
Expand All @@ -67,15 +68,29 @@ async function autoscript() {
setTimeout(() => {
from([1])
.pipe(
mergeMap(() => {
map(() => {
if (preAuthenticated === 'true') {
console.log('Set mock cookie to represent existing session');
document.cookie = 'iPlanetDirectoryPro=abcd1234; domain=localhost; path=/';
if (code && state) {
window.sessionStorage.setItem(
`FR-SDK-authflow-${clientId}`,
JSON.stringify({ responseType: 'code', state, verifier: '1234' }),
);
}
}
return;
}),
rxDelay(delay),
mergeMap((step) => {
let tokens;
// detect when in iframe as to not call `/authorize` needlessly
if (window.self !== window.top) {
if (error) {
// Do nothing
return;
} else if (code && state) {
tokens = forgerock.TokenManager.getTokens({
login: 'redirect',
query: { code, state },
query: { code, state, acr_values },
});
} else {
tokens = forgerock.TokenManager.getTokens({
Expand All @@ -98,7 +113,6 @@ async function autoscript() {
console.log('Remove cookie');
document.cookie = '';
console.log('Initiate logout');
// You have to allow specific origins to CORS for OAuth client
return forgerock.FRUser.logout();
}),
)
Expand All @@ -116,14 +130,12 @@ async function autoscript() {
}
console.log(`Error: ${err.message}`);
document.body.innerHTML = `<p class="Test_Complete">${err.message}</p>`;
localStorage.clear();
},
complete: () => {
console.log('Test script complete');
document.body.innerHTML = `<p class="Test_Complete">Test script complete</p>`;
localStorage.removeItem('wellknown');
localStorage.removeItem('clientId');
localStorage.removeItem('realmPath');
localStorage.removeItem('scope');
localStorage.clear();
},
});
}, 250);
Expand Down
2 changes: 1 addition & 1 deletion e2e/autoscript-apps/src/authn-central-login/autoscript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* autoscript.ts
*
* Copyright (c) 2020 ForgeRock. All rights reserved.
* Copyright (c) 2020 - 2025 Ping Identity Corporation. All rights reserved.
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
Expand Down
Loading
Loading