PingAM

Web authentication (WebAuthn) and passkeys

WebAuthn lets users authenticate with an authenticator device, such as the fingerprint scanner on their laptop or phone. The user’s browser communicates with the authenticator device.

Passkeys are a form of WebAuthn credential. They let users sign in without a password by using a built-in authenticator, such as Face ID, Touch ID, or Windows Hello, or a hardware security key. Passkeys can be synced across devices using a platform provider, such as iCloud Keychain or Google Password Manager, making them both phishing-resistant and easy to use.

AM supports passkeys through the WebAuthn Authentication and WebAuthn Registration nodes. You can configure passkeys for standard two-factor authentication, for passkey autofill (conditional UI), or for usernameless, passwordless authentication.

AM can request the browser to activate the authenticator device with certain criteria; for example:

  • The authenticator device must be built-in, not a USB device that the user can eject

  • The device must verify the user’s identity, not just the user’s presence

To use WebAuthn with AM, users must first register their authenticators. If recovery codes are enabled, users should copy their codes on successful registration.

Registration involves the selected authenticator creating, or minting, a key pair. The public key of the pair is returned to AM and stored in the user’s profile. The private key is stored securely in the authenticator itself or in the platform that manages the authenticators. The private key does not leave the client at any time.

When authenticating with WebAuthn, the authenticator device locks data with its stored private key and sends it to AM. AM verifies the data using the public key stored in the user’s profile. If the data verification succeeds and passes any attestation checks, AM considers the authentication successful.

  • If the authenticator provides an attestation that contains an invalid certificate chain (including the root CA certificate in the chain), AM rejects the attestation and throws an InvalidDataException error. The root certificate must be issued and securely distributed by a Certificate Authority.

  • To use WebAuthn, the end user must connect over HTTPS.

AM supports WebAuthn for the following user agents on the specified platforms:

Browsers and platforms supported for WebAuthn
Browser(1) Platform

Google Chrome

Desktop

Android

Safari

Desktop

iOS

Microsoft Edge

Desktop

Mozilla Firefox

Desktop

(1) Latest stable versions are supported.

Common use cases

WebAuthn suits deployments that need strong, phishing-resistant authentication:

  • Phishing-resistant workforce sign-on: Users sign on with a built-in authenticator, such as Windows Hello or Touch ID, or a hardware security key. The private key isn’t exposed to AM or the website. Depending on the authenticator, credentials are bound to a single device or synchronized across a user’s devices.

  • Passkey autofill (conditional UI): Users who have saved a passkey in their browser see it offered in the username field’s autofill list; users who haven’t saved one fall back to their password or another method. This suits gradual passkey adoption alongside existing credentials. Learn more in Configure WebAuthn conditional UI.

  • Usernameless sign-on: Users authenticate with a resident-key credential and an authorization gesture, without entering a username or password. This suits users signing on from their own devices who want a sign-on experience with nothing to type. Learn more in Configure usernameless authentication.

  • Platform authenticator deployments: Built-in authenticators, such as fingerprint scanners, suit users who sign on from managed laptops and phones.

  • Recovery codes: Users who replace or lose their authenticator can sign on with recovery codes and register a new device. The original registration journey must enable and generate recovery codes.

Create trees for WebAuthn

The example tree that follows registers the user’s device if necessary, and authenticates the user with the device. If the user has already registered their device, they only need to enter their username, and then perform the authorization gesture with their registered device to complete authentication.

If the user does not have a registered device, they must provide both their username and their password. The Data Store Decision node confirms their identity before allowing them to register their device. The user then authenticates with the new device to complete authentication.

The tree created here does not include user-friendly features, such as letting the user retry their password if they mistype it.

Configure the WebAuthn Profile Encryption service

In the AM admin UI, configure the WebAuthn Profile Encryption service for the realm where you create the tree.

This service configures how AM stores registered device metadata.

  1. In the AM admin UI for the realm, click Services > Add a Service.

  2. Select WebAuthn Profile Encryption Service in the service type drop-down list, and create the new service configuration.

  3. Accept the default configuration unless you must encrypt the device metadata in user profiles:

    Profile Storage Attribute

    webauthnDeviceProfiles (default)

    Device Profile Encryption Scheme

    If you choose an encryption scheme, also edit the settings to access the keys.

    For details, read Secrets, certificates, and keys.

    Default: No encryption of device settings.

    For detailed information about the available properties, refer to WebAuthn profile encryption service.

Create the WebAuthn tree

  1. Configure the WebAuthn Profile Encryption service for the realm if you have not already done so.

  2. In the AM admin UI, create a tree for WebAuthn under Realms > realm name > Authentication > Trees.

  3. Add the following nodes to your tree:

  4. Connect the nodes as demonstrated in the following figure:

    A tree for WebAuthn authentication.
  5. On the WebAuthn Authentication node, select Allow recovery codes.

  6. On the WebAuthn Registration node, select Generate recovery codes.

  7. Save your changes.

Test the WebAuthn tree

  1. Register a test user account unless you have already done so.

  2. In an incognito browser window, browse to the WebAuthn tree.

    The URL looks something like:
    https://am.example.com:8443/am/XUI/?realm=/alpha&service=myWebAuthnTree#login

    A login screen prompts for the username.

  3. Enter the username for the test user account.

  4. If the user does not have a registered device:

    1. Enter the test user’s password when prompted.

    2. Register a WebAuthn authenticator by performing an authorization gesture.

      For example, press the button on a connected YubiKey or scan your fingerprint.

      WebAuthn registration waiting for an authenticator

      The browser may present a consent pop-up to allow access to the available authenticators.

      When you grant consent, the browser activates the relevant authenticators, ready for registration.

      If the device registration is successful, the tree returns to the WebAuthn Authentication node.

  5. When prompted, authenticate by performing an authorization gesture with a registered device.

    The UI displays the user profile page.

    The dashboard page lists the registered devices that you can rename or delete.

    The default name for a new WebAuthn device is New Security Key.

Configure WebAuthn conditional UI

The WebAuthn conditional UI, also known as passkey autofill, lets users sign in with a passkey if they’ve previously saved one in their browser. If they don’t have a suitable passkey, the browser lets them authenticate using a different method, such as their username and password or social authentication.

This feature provides a more seamless login experience to end users and can help increase the adoption of passkeys.

To provide the conditional UI functionality, create a WebAuthn journey with the following configuration:

  • Include a v2.0 WebAuthn Authentication node with the following settings:

    • Username from device: Enabled

    • Mediation: CONDITIONAL

    • Authentication Button: Optionally, enable this option if you want to show users a Sign in with passkey button.

  • Place the WebAuthn Authentication node in a v2.0 Page node.

  • Optionally, include a v2.0 WebAuthn Registration node. If included, it must have the following setting:

    • Username to device: Enabled

  • Optionally, configure the following if you want to include passkey autofill suggestions when the user is prompted for their username:

    1. Place the Username Collector node or the Platform Username node in the same Page node as the WebAuthn Authentication node.

    2. In the Username Collector or Platform Username node, configure the following autocomplete values:

      username
      webauthn

      The autocomplete values must be in this order.

Create a journey for WebAuthn conditional UI

The following example journey provides WebAuthn conditional UI functionality with passkey autofill suggestions and a Sign in with passkey button:

  1. Configure the WebAuthn Profile Encryption service for the realm if you haven’t already done so.

  2. In the AM admin UI, create a tree for WebAuthn under Realms > realm name > Authentication > Trees.

  3. Add the following nodes to your tree:

  4. Connect the nodes as demonstrated in the following figure:

    A tree for WebAuthn conditional UI
  5. On the Username Collector node:

    • Add the following values to the Autocomplete Values field:

      username
      webauthn

  6. On the WebAuthn Authentication node:

    • Enable Username from device.

    • Select CONDITIONAL in the Mediation field.

    • Enable Authentication Button.

  7. Save your changes.

The user will see a login page similar to the following:

Example login page with WebAuthn conditional UI

Configure usernameless authentication

AM lets you create a secure and seamless login experience by authenticating end users with any credential on their device that supports FIDO2 WebAuthn.

You can also extend passwordless authentication to include usernameless authentication with popular authenticators that support resident keys; for example, Windows Hello (biometric authenticators).

To use usernameless authentication, the end user must:

  • Register an authenticator that supports resident keys in their profile.

  • Enable the option to associate a certificate on their device with their username.

When registered, the end user can use that device to authenticate, without having to provide their credentials; they need to select the appropriate entry to use from the list their device provides.

To configure usernameless authentication:

  1. Create a web authentication registration tree to associate a device that supports resident keys with an end user.

  2. Create a second tree that lets users authenticate to AM without entering their username or password.

The trees shown in these examples don’t include user-friendly features, such as allowing retries or redirecting for further help on failures.

Create a usernameless registration tree

  1. Configure the WebAuthn Profile Encryption service for the realm if you have not already done so.

  2. In the AM admin UI, create a tree for registration under Realms > realm name > Authentication > Trees.

    In this example, the tree is named myUsernamelessRegTree.

  3. Add the following nodes to your tree:

    • Data Store Decision node

    • Page node

    • Username Collector node

    • Password Collector node

    • WebAuthn Registration node

    • (Optional) Scripted Decision node

      By default, the WebAuthn Registration node stores the tree’s shared state variable username on the device. During authentication, this value later identifies the user.

      Use a Scripted Decision node to customize the display name or string to be saved in the shared state.

      Script to set the display name
      • Next-generation

      • Legacy

      var user = nodeState.get('username');
      var identity = idRepository.getIdentity(user);
      
      var displayName = '';
      
      var givenName = identity.getAttributeValues('givenName')[0];
      var surname = identity.getAttributeValues('sn')[0];
      var email = identity.getAttributeValues('mail')[0];
      
      if (givenName) {
        displayName += givenName;
      }
      
      if (surname) {
        displayName += ' ' + surname;
      }
      
      if (email) {
        displayName += ' (' + email + ')';
      }
      
      if (displayName) {
        nodeState.putShared('displayName', displayName);
      } else {
        nodeState.putShared('displayName', user);
      }
      action.goTo("true");
      var fr = JavaImporter(org.forgerock.openam.auth.node.api.Action);
      
      var user = nodeState.get('username').asString();
      var displayName = '';
      
      var givenName = idRepository.getAttribute(user, 'givenName');
      var surname = idRepository.getAttribute(user, 'sn');
      var email = idRepository.getAttribute(user, 'mail');
      
      if (givenName) {
        displayName += givenName.toArray()[0];
      }
      
      if (surname) {
        displayName += ' ' + surname.toArray()[0];
      }
      
      if (email) {
        displayName += ' (' + email.toArray()[0] + ')';
      }
      
      if (displayName) {
        nodeState.putShared('displayName', displayName.toString());
      } else {
        nodeState.putShared('displayName', user.toString());
      }
      action = fr.Action.goTo("true").build();
  4. Connect the nodes as demonstrated in the following figure:

    A tree for usernameless device registration.

    If you do not use the Scripted Decision node, connect the Data Store Decision node True output directly to the WebAuthn Registration node.

  5. If you use the Scripted Decision node:

    1. Select your script in the Script dropdown.

    2. Add the outcome of your script, true in this example, in the Outcomes field.

  6. On the WebAuthn Registration node:

    1. Enable Username to device.

    2. If you do not use the Scripted Decision node, add userName in the Shared state attribute for display name field.

    3. If you use the Scripted Decision node, add the shared state variable name, such as displayName, in the Shared state attribute for display name field.

  7. Save your changes.

Create a usernameless authentication tree

  1. Configure the WebAuthn Profile Encryption service for the realm if you haven’t already done so.

  2. In the AM admin UI, create a tree for usernameless authentication under Realms > realm name > Authentication > Trees.

    In this example, the tree is named myUsernamelessAuthTree.

  3. Add a WebAuthn Authentication node to your tree.

  4. Connect the nodes as demonstrated in the following figure:

    A tree for usernameless device authentication.
  5. On the WebAuthn Authentication node, enable Username from device.

  6. Save your changes.

Register for usernameless authentication

Follow these steps to register a device for usernameless authentication, and then authenticate with no username or password, only an authorization gesture.

  1. Create a test user account if you don’t already have one.

  2. In an incognito browser window, browse to the usernameless registration tree.

    The URL looks something like:
    https://am.example.com:8443/am/XUI/?realm=/alpha&service=myUsernamelessRegTree#login

    A login screen prompts for your credentials.

  3. Sign in with the username and password of the test user.

  4. If you’re authenticating from a FIDO2-enabled device, it prompts you for the method to verify your identity.

    For example, you might use a USB security key or a built-in biometric sensor.

    Select the option to associate with the user.

  5. Perform the authorization gesture of the chosen option when asked to do so.

    For example, press the button on your USB security key or scan your fingerprint.

    The UI displays the user profile page.

    The dashboard page lists the registered devices that you can rename or delete.

Authenticate with usernameless authentication

After registering, authenticate the test user without a username or password as follows:

  1. Sign out.

  2. In the same browser window, browse to the usernameless authentication tree.

    The URL looks something like:
    https://am.example.com:8443/am/XUI/?realm=/alpha&service=myUsernamelessAuthTree#login

  3. Perform the authorization gesture of the chosen option when prompted.

    A list of the accounts associated with the authentication device displays:

    Google Chrome presenting the accounts associated with Touch ID on the device.

    In this example, the user’s full name and email address appear. The Scripted Decision node gathered them during registration.

  4. Select the account to sign in.

    The UI displays the user profile page without you having to enter your username or password.

Configure WebAuthn trust anchors

The CA attestation type lets AM verify the authenticity of attestation data received from a device by using the relevant CA certificates.

If the trust chains defined by the CA certificates have CRL or OCSP entries, AM can also check for revocation.

To configure trust anchors in AM, obtain the CA-issued certificate chains for the devices you intend to verify, and make them available to AM in a secret store.

When the relevant certificate chains are in place, configure the WebAuthn Registration node with the alias of the secret store, and set Preferred mode of attestation to either DIRECT or INDIRECT.

Perform the following steps to enable trust anchors and achieve CA attestation for trusted devices:

  1. Obtain the CA-issued certificate chains for the devices you want to verify.

    You might need to consult the device manufacturer to obtain the certificate chains.

  2. Import the certificate chains into a keystore:

    $ keytool -import \
      -file /Downloads/vendor-a-ca.crt \
      -alias "vendor-a-devices" \
      -storetype JCEKS \
      -storepass changeit \
      -keystore /path/to/am/security/keystores/webauthnTrustStore.jceks

    This command imports a hypothetical trust chain from "Vendor A" into a secret store named webauthnTrustStore.jceks, located in the default AM path for keystores, /path/to/am/security/keystores.

    If the keystore does not exist, the command creates it and sets the store password to changeit; otherwise, it adds the specified certificate to the secret store.

  3. Repeat the previous step until the webauthnTrustStore.jceks secret store contains all the CA-issued certificate chains for the devices you want to verify.

  4. Ensure that the password to access the new webauthnTrustStore.jceks secret store is available to your AM instance; for example, by encrypting the password and adding the result to a new file named webauthnStorepass, in /path/to/am/security/secrets/encrypted.

    For more information, see File System Secret Volumes Secret Stores.

  5. In the AM admin UI, go to the realm containing the web authentication registration tree that will attempt CA-level attestation, go to Authentication > Trees, and click your registration tree.

  6. Select the WebAuthn Registration Node, and in the properties pane:

    • Set the Preferred mode of attestation property to DIRECT or INDIRECT.

    • Set the Trust Store alias property to a string that identifies the trust store, and is the suffix of the secret label used for mappings; for example, webauthnTrustStore.

    • To act upon the attestation type achieved when registering a device; for example, using a script, enable the Store data in transient state property.

      When you enable this property, the WebAuthn Registration Node stores the level of attestation achieved in a variable named webauthnAttestationType, in the tree’s transient state.

      Use code similar to the following JavaScript to read the value of webauthnAttestationType:

      var attestationLevel = transientState.get("webauthnAttestationType");
    • Save your changes.

      For more information on the available properties, see WebAuthn Registration node.

  7. Navigate back to the realm page, select Secret Stores, and click Add Secret Store.

  8. In Secret Store ID, enter the alias you specified in the registration node earlier; for example, webauthnTrustStore.

    Select the store type, specify the path to the store, and click Create.

    Adding a WebAuthn trust store to a realm.
  9. Set the Store password secret label to the name of the file you created earlier with the encrypted value of the store password in; for example, webauthnStorepass.

    Save your changes.

  10. On the Mappings tab, click Add Mapping.

  11. In Secret Label, select the secret label that begins with am.authentication.nodes.webauthn.truststore, and has the alias you specified earlier as the suffix.

    For example, am.authentication.nodes.webauthn.truststore.webauthnTrustStore.

  12. Enter the alias of the certificate chains you want to use for verification, and click Add.

    Repeat this step to add all the aliases of certificate chains you want to use for CA-level attestation:

    Adding a WebAuthn trust store mapping.
  13. Save your changes.

    Your registration tree is now ready to verify the attestation data against the list of configured certificate chains.

By default, a WebAuthn credential is bound to a single relying party identifier (RP ID), and browsers only offer the credential on origins that belong to that domain. For example, if your users register a passkey on one domain (app.example.com) and sign in from a related domain (login.example.net), the browser doesn’t offer the passkey.

Related Origin Requests (ROR) is a WebAuthn Level 3 feature that lets users register a credential on one web origin and use it on another related origin. For example, when using example.com as the shared RP ID, users can register on https://app.example.com and sign in from https://login.example.net.

AM supports ROR for browser-based WebAuthn flows. ROR doesn’t merge application domains or user profiles in AM. The applications must use the same user and WebAuthn device data.

Common use cases

  • Multi-region and country-code top-level domains: Allows multinational brands operating localized domains (for example, example.com, example.co.uk, example.fr) to share a single passkey across all country sites.

    A user registers once and can sign on seamlessly on any regional site.

  • Cross-brand and ecosystem domains: Enables companies operating across multiple associated brands or portals (for example, brand.com and brandrewards.com) to share passkeys without forcing users into duplicate registrations.

  • Internet vs. Intranet / Private Network Domains: Lets users register a passkey on an external, internet-facing domain (for example, company.com) and authenticate with that same passkey on a private or corporate network domain (for example, company.net.au or internal portal domains).

  • Passkey autofill and frictionless user experience: Lets browser password managers and credential providers suggest and autofill the same passkey on any related domain in the allowlist, providing a consistent user experience.

Before you start

To configure ROR in AM, you must have:

  • Control of the web tier serving the RP ID domain.

    This means you must control the servers or content delivery network (CDN) that serve the RP ID domain, the primary domain used for passkeys.

  • HTTPS on all origins involved.

    Browsers offer passkeys only in secure contexts.

Configure related origin requests

  1. Host a ROR configuration file at the following URL, where rp-id is the relying party identifier:

    https://rp-id/.well-known/webauthn

    • The file must contain only an origins array listing all origins that can use the relying party identifier. For example:

      {
        "origins": [
          "https://app.example.com",
          "https://login.example.net"
        ]
      }
    • The endpoint must be publicly reachable, unauthenticated, and served from the domain matching the configured RP ID.

    • Ensure no redirects are served for this path. Browsers request it directly and don’t follow redirects.

    • If the origin has a non-default port, include the port.

      Origins match exactly, character for character. For example, https://app.example.com:8443 doesn’t match https://app.example.com.

      Browsers fetch this file on the RP ID’s default HTTPS port (443) even when the application itself runs on another port. Serve the file on 443 regardless of the application port.
    • The file must be served over HTTPS with the application/json content type.

    • If you’re using PingGateway, configure PingGateway or a static web server to serve this exact path. Don’t place it under an AM journey or /json endpoint.

    • Only add origins that your organization controls and requires for the WebAuthn flow.

    • Use exact HTTPS origins. Don’t use wildcards or broad domains.

    • Protect the DNS, TLS certificates, web server, and deployment process for the ROR file.

    • Review the file when you add or retire an application.

    • Most browser implementations enforce a limit of five unique origin labels in /.well-known/webauthn. Lists exceeding five labels might have additional entries ignored by the browser.

  2. Verify that the file is publicly reachable at the exact URL and that its response contains valid JSON. For example:

    $ curl -i https://example.com/.well-known/webauthn
    {
      "origins": [
        "https://app.example.com",
        "https://login.example.net"
      ]
    }

    If your applications use one RP ID, host one /.well-known/webauthn file for that identifier. If you configure different RP IDs, host a file for each identifier.

  3. In your WebAuthn journey, configure the following nodes:

    • WebAuthn Registration node

      1. Set Relying party identifier to the shared RP ID.

      2. In the Origin domains property, add each complete origin that can start a registration or authentication ceremony. For example, add https://app.example.com and https://login.example.net.

      3. Enable Username to device.

        This setting enables discoverable credentials so the credential can be offered on other origins during authentication.

      4. Optionally enable Generate recovery codes if your users need a fallback mechanism.

    • WebAuthn Authentication node

      1. Set the Relying party identifier and Origin domains properties to the same values as the WebAuthn Registration node.

      2. Don’t enable Username from device unless this is a usernameless journey or it supports passkey autofill.

        When this setting is off, the node looks up the user’s registered credential by the journey’s username and scopes the browser ceremony to it. The browser applies related-origin rules to that request too.

      3. Use the No Device Registered outcome to route new users to the WebAuthn Registration node.

    When the user signs in from a second origin, collect the same username they registered with. The node uses this username to find the stored credential and to scope the ceremony. If you allow users to authenticate with a different username, the journey fails with the error No passkeys available.
  4. Test the configuration:

    1. Open the application on the first origin (https://app.example.com) and register a passkey.

    2. Log out, then log in from the second origin (https://login.example.net) with the same username.

      The browser offers the passkey and names the RP ID. For example: Use a saved passkey for example.com.

    3. Complete authentication.

      The session is issued by the same AM instance. No separate registration is needed on the second origin.

  • ROR support depends on the browser, the operating system, and the authenticator.

  • Test registration and authentication separately with the browsers and authenticators in your deployment.

  • This procedure applies to browser-based WebAuthn flows.

    Native applications use platform-specific mechanisms to associate applications with web origins.

Find more information about ROR in the WebAuthn Level 3 specification.

Troubleshoot a ROR configuration

The following errors can occur if you’ve misconfigured ROR in AM:

Symptom Likely cause Fix

SecurityError: The relying party ID is not a registrable domain suffix … no listed origin matched the caller

The calling origin is missing from the related-origins file or does not match exactly, including scheme, host, or port.

Add the calling origin to the file on the RP ID host, exactly as reported by the browser.

AM rejects registration or login with a login failure

The origin is missing from the node’s Origin domains list.

Add the origin (including its port, if applicable) to both WebAuthn nodes.

The browser doesn’t offer the saved passkey on the second origin

The browser doesn’t support related origin requests.

Use a supported browser: Chrome 128+, Edge 128+, Safari 18+, or Firefox 152+. Older browsers support same-origin login only.