Integrate a single-page app
This is part two of a four-part article, Integrate with PingOne Advanced Identity Cloud hosted pages.
Overview
Who is this article for?
This is part two of a step-by-step guide for developers that wish to use Ping SDK with Hosted Pages. The goal is to give you practical advice about themes and provide some best practices along the way.
Prior knowledge configuring PingOne Advanced Identity Cloud is helpful but not assumed.
What is a single-page app?
A single-page app (SPA) is an app that runs inside a browser and does not require page reloading during use. You use this type of app every day. For example: Gmail, Google Maps, Facebook, and GitHub.
An SPA is all about providing an outstanding user experience by imitating a "natural" environment in the browser—no page reloads, no extra wait time. An SPA lets you visit just one web page which uses JavaScript to load all content that requires JavaScript.
An SPA requests the markup and data independently, rendering pages straight in the browser. SPAs frequently use popular JavaScript frameworks like AngularJS, Vue.js, React, and more.
The Ping SDK for JavaScript
Use the Ping SDK for JavaScript to integrate your SPAs with your authorization server
The Ping SDK for JavaScript allows you to rapidly build JavaScript apps against REST APIs.
The Ping SDK for JavaScript supports:
-
Registration and Authentication Trees
-
Access Token Acquisition
-
Session Handling
Integrate a single-page app with PingOne Advanced Identity Cloud
Build the UI
Using the framework of your choice, create a new app. You will configure the app to authenticate using PingOne Advanced Identity Cloud.
When building your SPA, you have two options for integrating with ForgeRock:
Option 1: Integrate via APIs and build your own UI.
Option 2: Use the Hosted Pages in your app (Centralized UI).
The SDK supports both options, allowing you to tailor your experience to your needs. Choose the Option that best meets your project and use case requirements.
A custom UI vs a centralized UI
Building a custom UI for your SPA allows you to have full control of the user experience, the branding, and the theme of your app. A custom UI allows you full customization control, but requires more development effort. Each app that uses the platform must build its own UI.
This might be problematic for projects where various SPAs point to a central authentication point to gain authentication privileges. In this case, if the UI/UX requirements allow it, we recommend using a Centralized UI.
What is a centralized UI
The Ping SDKs let you configure multiple apps on multiple platforms. You can reuse the user interface from PingAM or your own web app. You do not have to manage authentication yourself.
As the UI is centralized in the cloud, changes you make to an authentication journey in PingAM are available to all apps that use the UI. You do not need to rebuild or redeploy the apps.
Since your app does not manage authentication journeys, it does not need access to user credentials. This reduces complexity and risk.
The Ping SDK manages and stores tokens - providing a seamless single sign-on experience.
Additionally, apps that use a centralized UI are not affected by the new third party cookie restrictions being rolled out in modern web browsers.
To learn more about centralized UI, visit Use centralized login.
Configure PingOne Advanced Identity Cloud
Before you begin, follow the instructions in one of the following sections:
In the following example, you configure:
- In Advanced Identity Cloud
-
-
OAuth2.0 provider
-
OAuth2.0 client
-
- In the client applications
-
-
JS
-
Configure the OAuth2.0 provider
-
In the Platform Admin UI, log in to the PingAM Native console.
-
In the PingAM Native console, click Services.
-
If there is no OAuth2 Provider, create one using the default settings.
-
In the OAuth2 Provider configuration, on the Consent tab, enable the Allow Clients to Skip Consent option.
-
On the Configure OAuth2 tab, enable the Issue Refresh Tokens option.
-
On the Advanced OpenID Connect tab, enable the claims_parameter_supported option.
Configure the OAuth2.0 client
-
In the PingAM Native console, navigate to Applications > OAuth 2.0 > Clients.
-
Create a new OAuth 2.0 client named “sdkPublicClient”.
-
Set the following properties:
-
Client ID = sdkPublicClient
-
Client secret = (leave blank)
-
Redirection URIs = https://localhost:8443
-
Scope(s) = openid profile email address
-
-
Click Create.
-
On the Core tab:
-
Set the Client type property to Public.
-
Disable the Allow wildcard ports in redirect URIs property.
-
-
Click Save.
-
On the Advanced tab:
-
In the Grant Types field, ensure that the Authorization Code value is present.
-
Set the Token Endpoint Authentication Method field to None.
-
Enable the Implied consent property.
To properly enable implied consent, the OAuth2 Provider must be configured to allow clients to skip consent. For more information, see the PingAM reference documentation.
-
-
Click Save.
Configure your app to use centralized UI
In this example, you use a centralized UI to authenticate your app.
You configure the app to use the PingOne Advanced Identity Cloud authentication hosted page you used in part one of this tutorial.
To learn more about centralized UI, visit Use centralized login. |
Let’s see how you can do that in more detail:
For this example, you are going to import the Ping SDK using the NPM package, assuming you are using a CommonJS Bundler.
A CDN proxy and other approaches are available.
const forgerock = require('@forgerock/javascript-sdk'); |
-
Create a centralized login instance using the
Config
class. -
There is a close relationship between your app configuration and your OAuth 2.0 client configuration. Make sure they match.
forgerock.Config.set({ serverConfig: { baseUrl: 'https://openam-forgerock-sdks.forgeblocks.com/am', timeout: 90000 }, realmPath: 'alpha', clientId: 'sdkPublicClient', redirectUri: 'https://localhost:8443', // Example: the alias from the prerequisites section scope: 'openid profile email address', });
-
Create a login button with the tag ‘#loginBtn’.
-
Initiate authentication using the centralized UI feature.
document.querySelector('#loginBtn').addEventListener('click', () => { /** * The key-value of `login: redirect` is what allows central-login. * @note async await could be used in place of promises for greater clarity */ forgerock .TokenManager .getTokens({ login: 'redirect' }) .then(() => {forgerock .UserManager .getCurrentUser() .then((user) => showUser(user)); }); });
-
Create a way to logout.
document.querySelector('#logoutBtn').addEventListener('click', () => { try { Forgerock .FRUser .logout() .then(() => location.assign(`${document.location.origin}`)) } catch (error) { console.error(error); } });