Creating a custom UI app to share across OIDC apps
In this tutorial you replace the default PingAM or PingOne Advanced Identity Cloud user interface for authentication with your own custom user interface.
You’ll use an existing JavaScript sample application to act as your custom UI. This app will step through your authentication journeys, and act as the central UI for one or more sample client apps.
Understanding the custom UI flow
When the Ping SDKs perform OIDC login they initiate the OAuth 2.0 Authorization Code flow on your PingOne Advanced Identity Cloud tenant or PingAM server.
Your server would usually use its built-in user interface to authenticate the user, before returning to the client app with the authorization code.
For this tutorial you’ll configure your server to use your custom UI app to authenticate users instead.
The overall authentication flow is as follows:
-
In the client app, when the user initiates sign on the client app calls the
/authorize
endpoint to start the OAuth 2.0 flow. -
The OAuth 2.0 client you configure in the server needs to authenticate the user, and redirects users to your custom UI.
It appends a
goto
query parameter to the URL, so that the custom UI app can redirect to the server after successful authentication. -
The custom UI starts the authentication journey, and steps through each node, handling the callbacks as necessary.
Note that the custom UI app does not perform any OAuth 2.0 operations itself. Its only role is to authenticate the user by stepping through the journey, and then returning back to the server with the session token, so that the server can continue the OAuth 2.0 flow.
-
The custom UI app renders the UI to handle any interactive callbacks in the journey. For example, to capture the username and password credentials.
-
When authentication is successful, the server issues a session token on behalf of the user to the custom UI app.
The following snippet shows how the custom sample app handles the successful authentication, and uses the
goto
parameter:Excerpt from/javascript/embedded-login/src/main.js
// Check URL for query parameters const url = new URL(document.location); const params = url.searchParams; const goto = params.get('goto'); const handleStep = async (step) => { switch (step.type) { case 'LoginSuccess': { if (goto != null) { // Journey complete // Return to server to issue auth code window.location.replace(goto); return; } ... } ... }
For security reasons your custom UI must validate that the URL in the
goto
parameter matches a domain you trust before redirecting to it.Failure to validate the domain of the
goto
URL before redirecting could result in link hijacking or other security-related problems. -
Due to the presence of the
goto
parameter, the custom UI app can now redirect to the OAuth 2.0/authorize
endpoint, using the session token to authenticate the request.To authenticate the user the browser attaches the session token as a cookie in the request to the
/authorize
endpoint.Your server issues session token cookies for use on the same domain you have assigned to it. That domain will be one of the following:
-
The original URL for the server, for example:
-
openam-forgerock-sdks.forgeblocks.com
(PingOne Advanced Identity Cloud tenants) -
openam.example.com
(PingAM servers)
-
-
A custom domain assigned to the server, for example:
-
id.mycompany.com
-
If the custom UI app is running on a different domain than your server then browsers consider the cookie to be from a third party.
Some browsers, such as Safari block access to third-party cookies, so the requests that use them appear to not be authenticated.
For this tutorial you can disable third-party cookie checks in the browser, but for production you must ensure your custom UI and your server are sharing the same domain.
-
-
The OAuth 2.0 client accepts the request, and returns the authorization code to the client application.
The URL of the client app must match one of the redirect URIs listed in the OAuth 2.0 client configuration.
-
The client application recognizes that an authorization code is present and that authentication was a success, and can now exchange the authorization code by calling the
/access_token
OAuth 2.0 endpoint. -
The server validates the authorization code and issues the access token, an ID token, and if enabled, refresh tokens.
The client app can now call the
userinfo
endpoint, using the access token as a bearer token for authentication, and retrieve information about the user.
Tutorial steps
Complete the following tasks to try out this tutorial: