---
title: Part 3. Running a client sample app
description: In this section you configure one of the OIDC (centralized login) sample apps to test out your custom UI.
component: orchsdks
page_id: orchsdks:oidc:use-cases/custom-login-ui/03-run-a-client-oidc-app
canonical_url: https://developer.pingidentity.com/orchsdks/oidc/use-cases/custom-login-ui/03-run-a-client-oidc-app.html
revdate: Thu, 24 Apr 2025 14:44:20 +0100
keywords: ["OAuth 2.0", "OpenID Connect", "SDK"]
section_ids:
  running_the_javascript_sample_oidc_client_app: Running the JavaScript sample OIDC client app
  try_it_out: Try it out
  running_the_android_sample_oidc_client_app: Running the Android sample OIDC client app
  try_it_out_2: Try it out
  running_the_ios_sample_oidc_client_app: Running the iOS sample OIDC client app
  try_it_out_3: Try it out
---

# Part 3. Running a client sample app

In this section you configure one of the OIDC (centralized login) sample apps to test out your custom UI.

## Running the JavaScript sample OIDC client app

1. In a JavaScript-capable IDE, open the `sdk-sample-apps` folder you downloaded earlier.

2. Open the `/javascript/central-login-oidc` sample.

3. Edit the values in the `.env.sample` file to match your environment:

   1. In **SCOPE**, enter the list of scopes to request are present in the issued OAuth 2.0 token.

      For example, `"openid profile email phone address"`

   2. In **WEB\_OAUTH\_CLIENT**, enter the client ID of the OAuth 2.0 client you configured earlier.

      For example, `sdkCustomUI`

   3. In **WELL\_KNOWN**, enter the `.well-known` URL of the realm in which you created the OAuth 2.0 client.

      > **Collapse: How do I find my PingOne Advanced Identity Cloud  URL?**
      >
      > You can view the `.well-known` endpoint for an OAuth 2.0 client in the PingOne Advanced Identity Cloud admin console:
      >
      > 1. Log in to your PingOne Advanced Identity Cloud administration console.
      >
      > 2. Click Applications, and then select the OAuth 2.0 client you created earlier. For example, sdkPublicClient.
      >
      > 3. On the Sign On tab, in the Client Credentials section, copy the Discovery URI value.
      >
      >    For example, `https://openam-forgerock-sdks.forgeblocks.com/am/oauth2/alpha/.well-known/openid-configuration`
      >
      > |   |                                                                                                                                                                                                                                                                                                                                 |
      > | - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
      > |   | If you are using a custom domain, your `.well-known` is formed as follows:`https://<custom-domain-fqdn>/.well-known/openid-configuration`Learn more in [Access OIDC configuration discovery endpoint](https://docs.pingidentity.com/pingoneaic/latest/realms/custom-domains.html#access-oidc-configuration-discovery-endpoint). |

      > **Collapse: How do I find my PingAM  URL?**
      >
      > To form the `.well-known` URL for an PingAM server, concatenate the following information into a single URL:
      >
      > 1. The base URL of the PingAM component of your deployment, including the port number and deployment path.
      >
      >    For example, `https://openam.example.com:8443/openam`
      >
      > 2. The string `/oauth2`
      >
      > 3. The hierarchy of the realm that contains the OAuth 2.0 client.
      >
      >    You must specify the entire hierarchy of the realm, starting at the Top Level Realm. Prefix each realm in the hierarchy with the `realms/` keyword.
      >
      >    For example, `/realms/root/realms/customers`
      >
      >    |   |                                                                                 |
      >    | - | ------------------------------------------------------------------------------- |
      >    |   | If you omit the realm hierarchy, the top level `ROOT` realm is used by default. |
      >
      > 4. The string `/.well-known/openid-configuration`
      >
      > For example, `https://openam.example.com:8443/openam/oauth2/realms/root/.well-known/openid-configuration`

      The result will resemble the following:

      Example `.env.example` file

      ```text
      SCOPE='openid profile email phone address'
      TIMEOUT=1000
      WEB_OAUTH_CLIENT=sdkCustomUI
      WELL_KNOWN=https://openam-docs-regular.forgeblocks.com/am/oauth2/alpha/.well-known/openid-configuration
      SERVER_TYPE=AIC
      ```

4. Save the file as `.env` in the same folder.

5. Edit the `webpack.config.js` file.

   1. In the `devServer` section, add the DNS alias you created earlier, for example `sdkapp.example.com` in a new `allowedHosts` property:

      ```javascript
      devServer: {
          port: 8443,
          host: 'localhost',
          allowedHosts: 'sdkapp.example.com',
          …​
      }
      ```

6. From the `/javascript` folder, run the central login OIDC sample app as follows:

   ```none
   cd javascript
   npm run start:central-login-oidc
   ```

   Webpack compiles the code and serves it on the local IP address of your computer.

### Try it out

To test that your custom UI app is acting as the centralized login pages, perform the following steps.

1. In a browser, open the local IP address of your computer, with the port number you edited earlier.

   For example, `https://sdkapp.example.com:8443`

2. As the custom UI sample app is running on a self-signed SSL certificate on your local IP address, your browser might display a warning message.

   You can ignore this warning for this tutorial:

   * In **Chrome**, click **Advanced** and then click **Proceed to sdkapp.example.com (unsafe)**.

   * In **Firefox**, click **Advanced** and then click **Accept the risk and continue**.

   * In **Safari**, click **Show Details** and then click **visit this website**.

   The sample OIDC login app displays **Login** and **Force Renew** buttons:

   ![js central sample page 1 en](../../_images/js-central-sample-page-1-en.png)Figure 1. JavaScript OIDC sample app showing **Login** and **Force Renew** buttons.

3. Click the **Login** button.

   The client app connects to the OAuth 2.0 client you created earlier, and is redirected to the custom UI sample running on your local computer.

   The URL contains a `goto` parameter that contains the URL that the UI sample app redirects to after successful authentication. That URL will be the `authorize` endpoint of your authorization server.

4. Enter the credentials of a known user, and then click **Sign In**.

   1. If authentication is successful, the custom UI app redirects the browser to the `goto` URL, which points to your authorization server. The authorization server redirects back to your client app with the necessary `code` parameter.

   2. The sample client app uses the `code` parameter to contact the authorization server `access_token` endpoint to obtain the OAuth 2.0 access and ID tokens.

   3. Using the access token as a bearer token, the sample app calls the `userinfo` endpoint and displays them on the page:

      ![aic am oidc login userinfo](../../_images/aic-am-oidc-login-userinfo.png)Figure 2. Userinfo of the authenticated user.

## Running the Android sample OIDC client app

1. In **Android Studio**, open the `/android/kotlin-central-login-oidc` sample from the repo you downloaded earlier.

2. Edit the **app > kotlin+java > `Config.kt`** file to match your environment:

   1. In **discoveryEndpoint**, enter the `.well-known` URI of the realm in which you created the OAuth 2.0 client.

      > **Collapse: How do I find my PingOne Advanced Identity Cloud  URL?**
      >
      > You can view the `.well-known` endpoint for an OAuth 2.0 client in the PingOne Advanced Identity Cloud admin console:
      >
      > 1. Log in to your PingOne Advanced Identity Cloud administration console.
      >
      > 2. Click Applications, and then select the OAuth 2.0 client you created earlier. For example, sdkPublicClient.
      >
      > 3. On the Sign On tab, in the Client Credentials section, copy the Discovery URI value.
      >
      >    For example, `https://openam-forgerock-sdks.forgeblocks.com/am/oauth2/alpha/.well-known/openid-configuration`
      >
      > |   |                                                                                                                                                                                                                                                                                                                                 |
      > | - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
      > |   | If you are using a custom domain, your `.well-known` is formed as follows:`https://<custom-domain-fqdn>/.well-known/openid-configuration`Learn more in [Access OIDC configuration discovery endpoint](https://docs.pingidentity.com/pingoneaic/latest/realms/custom-domains.html#access-oidc-configuration-discovery-endpoint). |

      > **Collapse: How do I find my PingAM  URL?**
      >
      > To form the `.well-known` URL for an PingAM server, concatenate the following information into a single URL:
      >
      > 1. The base URL of the PingAM component of your deployment, including the port number and deployment path.
      >
      >    For example, `https://openam.example.com:8443/openam`
      >
      > 2. The string `/oauth2`
      >
      > 3. The hierarchy of the realm that contains the OAuth 2.0 client.
      >
      >    You must specify the entire hierarchy of the realm, starting at the Top Level Realm. Prefix each realm in the hierarchy with the `realms/` keyword.
      >
      >    For example, `/realms/root/realms/customers`
      >
      >    |   |                                                                                 |
      >    | - | ------------------------------------------------------------------------------- |
      >    |   | If you omit the realm hierarchy, the top level `ROOT` realm is used by default. |
      >
      > 4. The string `/.well-known/openid-configuration`
      >
      > For example, `https://openam.example.com:8443/openam/oauth2/realms/root/.well-known/openid-configuration`

   2. In **oauthClientId**, enter the client ID of the OAuth 2.0 client you configured earlier.

      For example, `sdkCustomUI`

   3. In **oauthRedirectUri**, enter the redirect URI you configured in the OAuth 2.0 client.

      For example, `org.forgerock.demo://oauth2redirect`

   4. In **cookieName**, enter the name of the cookie your authorization server uses to store session tokens on the client.

      For example, PingAM servers use `iPlanetDirectoryPro`

      > **Collapse: How do I find my PingOne Advanced Identity Cloud cookie name?**
      >
      > To locate the cookie name in an PingOne Advanced Identity Cloud tenant:
      >
      > 1. Navigate to Tenant settings > Global Settings
      >
      > 2. Copy the value of the Cookie property.

   5. In **oauthScope**, enter the list of scopes to request are present in the issued OAuth 2.0 token.

      For example, `openid profile email phone address`

   The result will resemble the following:

   ```kotlin
   data class PingConfig(
       var discoveryEndpoint: String = "https://openam-forgerock-sdks.forgeblocks.com/am/oauth2/realms/alpha/.well-known/openid-configuration",
       var oauthClientId: String = "sdkCustomUI",
       var oauthRedirectUri: String = "org.forgerock.demo://oauth2redirect",
       var oauthSignOutRedirectUri: String = "",
       var cookieName: String = "ch15fefc5407912",
       var oauthScope: String = "openid profile email phone address"
   )
   ```

3. Save your changes.

### Try it out

To test that your custom UI app is acting as the centralized login pages, perform the following steps.

1. In Android Studio, on the **Run** menu, select **Run 'ping-oidc.app'**.

   Android Studio compiles and launches the app in either your connected device or a simulator, and displays the configuration you entered earlier:

   ![kotlin oidc app android config](../../_images/kotlin-oidc-app-android-config.png)Figure 3. Android sample app showing the configuration.

   |   |                                                  |
   | - | ------------------------------------------------ |
   |   | You can alter the values in the app if required. |

2. Click **Launch OIDC Redirect Login**.

3. As the custom UI sample app is running on a self-signed SSL certificate on your local IP address, your browser might display a warning message.

   You can ignore this warning for this tutorial:

   * In **Chrome**, click **Advanced** and then click **Proceed to 192.168.0.35 (unsafe)**.

   * In **Firefox**, click **Advanced** and then click **Accept the risk and continue**.

   The client app connects to the OAuth 2.0 client you created earlier, and is redirected to the custom UI sample running on your local computer.

   The URL contains a `goto` parameter that contains the URL that the UI sample app redirects to after successful authentication. That URL will be the `authorize` endpoint of your authorization server.

4. Enter the credentials of a known user, and then click **Sign In**.

   1. If authentication is successful, the custom UI app redirects the browser to the `goto` URL, which points to your authorization server. The authorization server redirects back to your client app with the necessary `code` parameter.

   2. The sample client app uses the `code` parameter to contact the authorization server `access_token` endpoint to obtain the OAuth 2.0 access and ID tokens:

      ![kotlin oidc app android access token](../../_images/kotlin-oidc-app-android-access-token.png)Figure 4. Android OIDC sample app showing the access and ID tokens.

   3. Tap the menu icon ([icon: bars, set=fas]), and then tap User Profile:

      The OIDC sample app uses the access token as a bearer token and calls the `userinfo` endpoint, displaying the result:

      ![kotlin oidc app android userinfo](../../_images/kotlin-oidc-app-android-userinfo.png)Figure 5. Userinfo of the authenticated user.

## Running the iOS sample OIDC client app

1. In **Xcode**, in the `sdk-sample-apps` folder you cloned in the previous step, open the `iOS` > `swiftui-oidc` > `PingExample` > `PingExample.xcodeproj` file.

2. Locate the `ConfigurationViewModel` function which contains placeholder configuration properties.

   |   |                                                                                     |
   | - | ----------------------------------------------------------------------------------- |
   |   | The function is commented with `//TODO:` in the source to make it easier to locate. |

   ```swift
   return ConfigurationViewModel(
       clientId: "[CLIENT ID]",
       scopes: ["openid", "email", "address", "phone", "profile"],
       redirectUri: "[REDIRECT URI]",
       signOutUri: "[SIGN OUT URI]",
       discoveryEndpoint: "[DISCOVERY ENDPOINT URL]",
       environment: "[ENVIRONMENT - EITHER AIC OR PingOne]",
       cookieName: "[COOKIE NAME - OPTIONAL (Applicable for AIC only)]",
       browserSeletorType: .authSession
   )
   ```

   1. In **clientId**, enter the client ID of the OAuth 2.0 client you configured earlier.

      For example, `sdkCustomUI`

   2. In **scopes**, enter an array of scopes to request are present in the issued OAuth 2.0 token.

      For example, `["openid","profile","email","address","phone"]`

   3. In **redirectUri** and **signOutUri**, enter the redirect URI you configured in the OAuth 2.0 client.

      For example, `org.forgerock.demo://oauth2redirect`

   4. In **discoveryEndpoint**, enter the `.well-known` URI of the realm in which you created the OAuth 2.0 client.

      > **Collapse: How do I find my PingOne Advanced Identity Cloud  URL?**
      >
      > You can view the `.well-known` endpoint for an OAuth 2.0 client in the PingOne Advanced Identity Cloud admin console:
      >
      > 1. Log in to your PingOne Advanced Identity Cloud administration console.
      >
      > 2. Click Applications, and then select the OAuth 2.0 client you created earlier. For example, sdkPublicClient.
      >
      > 3. On the Sign On tab, in the Client Credentials section, copy the Discovery URI value.
      >
      >    For example, `https://openam-forgerock-sdks.forgeblocks.com/am/oauth2/alpha/.well-known/openid-configuration`
      >
      > |   |                                                                                                                                                                                                                                                                                                                                 |
      > | - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
      > |   | If you are using a custom domain, your `.well-known` is formed as follows:`https://<custom-domain-fqdn>/.well-known/openid-configuration`Learn more in [Access OIDC configuration discovery endpoint](https://docs.pingidentity.com/pingoneaic/latest/realms/custom-domains.html#access-oidc-configuration-discovery-endpoint). |

      > **Collapse: How do I find my PingAM  URL?**
      >
      > To form the `.well-known` URL for an PingAM server, concatenate the following information into a single URL:
      >
      > 1. The base URL of the PingAM component of your deployment, including the port number and deployment path.
      >
      >    For example, `https://openam.example.com:8443/openam`
      >
      > 2. The string `/oauth2`
      >
      > 3. The hierarchy of the realm that contains the OAuth 2.0 client.
      >
      >    You must specify the entire hierarchy of the realm, starting at the Top Level Realm. Prefix each realm in the hierarchy with the `realms/` keyword.
      >
      >    For example, `/realms/root/realms/customers`
      >
      >    |   |                                                                                 |
      >    | - | ------------------------------------------------------------------------------- |
      >    |   | If you omit the realm hierarchy, the top level `ROOT` realm is used by default. |
      >
      > 4. The string `/.well-known/openid-configuration`
      >
      > For example, `https://openam.example.com:8443/openam/oauth2/realms/root/.well-known/openid-configuration`

   5. In **environment**, enter `AIC`.

   6. In **cookieName**, enter the name of the cookie your authorization server uses to store session tokens on the client.

      For example, PingAM servers use `iPlanetDirectoryPro`

      > **Collapse: How do I find my PingOne Advanced Identity Cloud cookie name?**
      >
      > To locate the cookie name in an PingOne Advanced Identity Cloud tenant:
      >
      > 1. Navigate to Tenant settings > Global Settings
      >
      > 2. Copy the value of the Cookie property.

   7. In **browserSelectorType**, enter `.authSession`.

      You can specify what type of browser the client iOS device opens to handle centralized login.

      Each browser has slightly different characteristics, which make them suitable to different scenarios, as outlined in this table:

      | Browser type            | Characteristics                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
      | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
      | `.authSession`          | Opens a [web authentication session](https://developer.apple.com/documentation/authenticationservices/aswebauthenticationsession) browser.Designed specifically for authentication sessions, however it prompts the user before opening the browser with a modal that asks them to confirm the domain is allowed to authenticate them.This is the default option in the Orchestration SDK for iOS.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
      | `.ephemeralAuthSession` | Opens a [web authentication session](https://developer.apple.com/documentation/authenticationservices/aswebauthenticationsession) browser, but enables the [`prefersEphemeralWebBrowserSession`](https://developer.apple.com/documentation/authenticationservices/aswebauthenticationsession/prefersephemeralwebbrowsersession) parameter.This browser type *does not* prompt the user before opening the browser with a modal.The difference between this and `.authSession` is that the browser does not include any existing data such as cookies in the request, and also discards any data obtained during the browser session, including any session tokens.When is `ephemeralAuthSession` suitable:- [icon: times, set=fa]`ephemeralAuthSession` is *not* suitable when you require single sign-on (SSO) between your iOS apps, as the browser will not maintain session tokens.

      - [icon: times, set=fa]`ephemeralAuthSession` is *not* suitable when you require a session token to log a user out of the server, for example for logging out of PingOne, as the browser will not maintain session tokens.

      - [icon: check, set=fa]Use `ephemeralAuthSession` when you do not want the user's existing sessions to affect the authentication. |
      | `.nativeBrowserApp`     | Opens the installed browser that is marked as the default by the user. Often Safari.The browser opens without any interaction from the user. However, the browser does display a modal when returning to your application.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
      | `.sfViewController`     | Opens a [Safari view controller](https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller) browser.Your client app is ***not*** able to interact with the pages in the `sfViewController` or access the data or browsing history.The view controller opens within your app without any interaction from the user. As the user does not leave your app, the view controller does not need to display a warning modal when authentication is complete and control returns to your application.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |

   The result resembles the following:

   ```swift
   return ConfigurationViewModel(
       clientId: "sdkCustomUI",
       scopes: ["openid", "email", "address", "phone", "profile"],
       redirectUri: "org.forgerock.demo://oauth2redirect",
       signOutUri: "org.forgerock.demo://oauth2redirect",
       discoveryEndpoint: "https://openam-forgerock-sdks.forgeblocks.com/am/oauth2/realms/alpha/.well-known/openid-configuration",
       environment: "AIC",
       cookieName: "ch15fefc5407912",
       browserSeletorType: .authSession
   )
   ```

3. Save your changes.

### Try it out

To test that your custom UI app is acting as the centralized login pages, perform the following steps.

1. In Xcode, select **Product > Run**.

   Xcode launches the sample app in the iPhone simulator.

   ![ios custom ui menu](../../../_images/ios-custom-ui-menu.png)Figure 6. iOS OIDC login sample home screen

   |   |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
   | - | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
   |   | Third-party cookies in the Safari browserSafari blocks third-party cookies by default, so the custom UI app will not be able to authenticate calls to the `/authorize` endpoint if it is running on a different domain than the server.In production, ensure your custom UI app and server share the same domain.For this tutorial disable third-party cookie checks in Safari as follows:1) In the iPhone simulator, in the toolbar click **Home**. On the screen, use your mouse to swipe to the right, and then tap **Settings**.

   2) Tap **Safari**, scroll to the **Privacy & Security** section, and disable **Prevent Cross-Site Tracking**.

      ![safari allow cross site tracking](../../../_images/safari-allow-cross-site-tracking.png)Figure 7. Allow third-party cookies in Safari

   3) To return to the sample app, in the toolbar double-click **Home** to show the open apps, and then tap the **PingOIDC** app.

      ![ios switch to oidc app](../../../_images/ios-switch-to-oidc-app.png)Figure 8. Return to the OIDC sample app by double-clicking the home icon. |

2. In the sample app on the iPhone simulator, tap Edit configuration, and verify or edit the configuration you entered in the previous step.

   ![ios custom ui config](../../../_images/ios-custom-ui-config.png)Figure 9. Verify the configuration settings

3. Tap **[icon: chevron-left, set=fas, size=xs]Ping OIDC** to go back to the main menu, and then tap **Launch OIDC**.

   |   |                                                                                       |
   | - | ------------------------------------------------------------------------------------- |
   |   | You might see a dialog asking if you want to open a browser. If you do, tap Continue. |

   The app launches a web browser and connects to your authorization server, which then redirects to the custom UI app running locally on your computer:

   ![ios custom ui login](../../../_images/ios-custom-ui-login.png)Figure 10. Browser launched and redirected to local custom UI app.

4. Sign on as a demo user:

   * Name: `demo`

   * Password: `Ch4ng3it!`

   If authentication is successful, the application displays the access token issued by PingAM.

   ![ios custom ui token](../../../_images/ios-custom-ui-token.png)Figure 11. Access token after successful authentication

5. Tap [icon: chevron-left, set=fas, size=xs]Ping OIDC to go back to the main menu, and then tap User Info.

   The app displays the information relating to the access token:

   ![ios custom ui userinfo](../../../_images/ios-custom-ui-userinfo.png)Figure 12. User info relating to the access token

6. Tap [icon: chevron-left, set=fas, size=xs]Ping OIDC to go back to the main menu, and then tap Logout.

   The app logs the user out of the authorization server and prints a message to the Xcode console:

   ```text
   [FRCore][4.8.2] [🌐 - Network] Response | [✅ 204] :
     https://openam.example.com:443/am/oauth2/connect/endSession?id_token_hint=eyJ0...sbrA&client_id=sdkPublicClient in 34 ms
   [FRAuth][4.8.2] [FRUser.swift:211 : logout()] [Verbose]
     Invalidating OIDC Session successful
   ```
