Ping SDKs

Configure a JavaScript app for social sign-on

Perform the following steps to configure a JavaScript app for social sign-on using PingOne.

You can follow the steps in this tutorial using the embedded-login-davinci sample app, which supports social sign-on.

Step 1. Adding the module

You must add the davinci module to your project:

import { davinci } from '@forgerock/davinci-client';
typescript

Step 2. Handling the redirect back from the IdP

You must configure your JavaScript app to continue a flow when the server redirects the user back from the IdP.

Use the davinciClient.resume method to continue an existing flow, rather than start a new one.

const 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);
}
typescript

Step 3. Handling IdpCollector nodes

Your app must handle the IdpCollector node type that DaVinci sends. The node contains details of the button to render and the URL, for example.

Use the davinciClient.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());
  }
}
typescript

In this example, a socialLoginButtonComponent handles rendering the button and redirecting the user to the selected identity provider:

Example social-login-button.ts file to render social sign-on buttons
import 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);
}
typescript

The result resembles the following:

Example JavaScript app with social sign-on options.