Step 2. Authenticating with external IdPs
PingOne JavaScript
Your app must handle the relevant node types your server returns when a user attempts to authenticate using an external IdP.
A DaVinci flow returns an IdpCollector to the client, which contains details about the external IdP the user chose for authentication.
Handling external IdP nodes in DaVinci flows
When encountering a IdpCollector collector in a DaVinci flow, use the externalIdp() method to obtain the details from the collector:
const collectors = davinciClient.getCollectors();
collectors.forEach((collector) => {
if (collector.type === 'IdpCollector') {
socialLoginButtonComponent(formEl, collector, davinciClient.externalIdp());
}
}
In this example, a socialLoginButtonComponent handles rendering the button and redirecting the user to the selected identity provider:
social-login-button.ts file to render social sign-on buttonsimport type { IdpCollector } from "@forgerock/davinci-client/types";
export default function socialLoginButtonComponent(
formEl: HTMLFormElement,
collector: IdpCollector,
updater: () => void
) {
const button = document.createElement("button");
button.value = collector.output.label;
button.innerHTML = collector.output.label;
if (collector.output.label.toLowerCase().includes('google')) {
button.style.background = 'white'
button.style.borderColor = 'grey'
} else if (collector.output.label.toLowerCase().includes('facebook')) {
button.style.color = 'white'
button.style.background = 'royalblue'
button.style.borderColor = 'royalblue'
} else if (collector.output.label.toLowerCase().includes('apple')) {
button.style.color = 'white'
button.style.background = 'black'
button.style.borderColor = 'black'
}
button.onclick = async () => {
await updater();
window.location.assign(collector.output.url);
};
formEl?.appendChild(button);
}
After authenticating with the external IdP, they return to PingOne. PingOne generates a continueToken and attaches it as a query parameter to the URL that redirects back to the JavaScript client.
You must configure your JavaScript app to continue a flow on receipt of the continueToken.
Use the resume() method to continue an existing flow, rather than start a new one:
continueTokenconst davinciClient = await davinci({ config });
const urlParams = new URLSearchParams(window.location.search);
const continueToken = urlParams.get('continueToken');
let resumeNode;
if (continueToken) {
// Continue an existing flow
resumeNode = await davinciClient.resume({ continueToken });
} else {
// Setup configuration for a new flow
await Config.setAsync(config);
}