---
title: "MFA: Web authentication (WebAuthn) and passkeys"
description: 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.
component: pingam
version: 8.1
page_id: pingam:am-authentication:authn-mfa-webauthn
canonical_url: https://docs.pingidentity.com/pingam/8.1/am-authentication/authn-mfa-webauthn.html
keywords: ["Authentication", "Multi-factor Authentication (MFA)", "Web authentication (WebAuthn)", "passkey", "passkeys", "FIDO2", "passwordless"]
page_aliases: ["authentication-guide:authn-mfa-webauthn.adoc"]
section_ids:
  authn-mfa-web-authn: Create trees for WebAuthn
  mfa-webauthn-profile-encryption: Configure the WebAuthn Profile Encryption service
  create_the_webauthn_tree: Create the WebAuthn tree
  test_the_webauthn_tree: Test the WebAuthn tree
  webauthn-conditional-ui: Configure WebAuthn conditional UI
  create_a_journey_for_webauthn_conditional_ui: Create a journey for WebAuthn conditional UI
  webauthn-usernameless: Configure usernameless authentication
  create_a_usernameless_registration_tree: Create a usernameless registration tree
  create_a_usernameless_authentication_tree: Create a usernameless authentication tree
  try-usernameless-auth: Register for usernameless authentication
  authenticate_with_usernameless_authentication: Authenticate with usernameless authentication
  webauthn-trust-anchors: Configure WebAuthn trust anchors
---

# MFA: 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](https://docs.pingidentity.com/auth-node-ref/8.1/webauthn-authentication.html) and [WebAuthn Registration](https://docs.pingidentity.com/auth-node-ref/8.1/webauthn-registration.html) nodes. You can configure passkeys for standard two-factor authentication, for [passkey autofill (conditional UI)](#webauthn-conditional-ui), or for [usernameless, passwordless authentication](#webauthn-usernameless).

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.

## 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](https://www.w3.org/TR/webauthn/#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](https://docs.pingidentity.com/auth-node-ref/8.1/data-store-decision.html) 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 > [icon: plus, set=fa]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](../security/secrets-certs-keys.html).

     Default: `No encryption of device settings.`

     For detailed information about the available properties, refer to [WebAuthn profile encryption service](../setup/services-configuration.html#global-authenticatorwebauthnservice).

### Create the WebAuthn tree

1. [Configure the WebAuthn Profile Encryption service](#mfa-webauthn-profile-encryption) 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:

   * [Data Store Decision node](https://docs.pingidentity.com/auth-node-ref/8.1/data-store-decision.html)

   * [Username Collector node](https://docs.pingidentity.com/auth-node-ref/8.1/am-only/username-collector.html)

   * [Password Collector node](https://docs.pingidentity.com/auth-node-ref/8.1/am-only/password-collector.html)

   * [Recovery Code Collector Decision node](https://docs.pingidentity.com/auth-node-ref/8.1/recovery-code-collector-decision.html)

   * [Recovery Code Display node](https://docs.pingidentity.com/auth-node-ref/8.1/recovery-code-display.html)

   * [WebAuthn Authentication node](https://docs.pingidentity.com/auth-node-ref/8.1/webauthn-authentication.html)

   * [WebAuthn Registration node](https://docs.pingidentity.com/auth-node-ref/8.1/webauthn-registration.html)

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

   ![A tree for WebAuthn authentication.](_images/auth-tree-webauthn-auth-reg.png)

5. On the [WebAuthn Authentication node](https://docs.pingidentity.com/auth-node-ref/8.1/webauthn-authentication.html), select Allow recovery codes.

6. On the [WebAuthn Registration node](https://docs.pingidentity.com/auth-node-ref/8.1/webauthn-registration.html), 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](_images/trees-node-webauthn-waiting.png)

      |   |                                                                                                                                                                                             |
      | - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
      |   | 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](https://docs.pingidentity.com/auth-node-ref/8.1/webauthn-authentication.html).

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](https://docs.pingidentity.com/auth-node-ref/8.1/webauthn-authentication.html) 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.

* The WebAuthn Authentication node must be placed in a v2.0 [Page node](https://docs.pingidentity.com/auth-node-ref/8.1/page.html).

* Optionally, include a v2.0 [WebAuthn Registration node](https://docs.pingidentity.com/auth-node-ref/8.1/webauthn-registration.html). 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](https://docs.pingidentity.com/auth-node-ref/8.1/am-only/username-collector.html) or the [Platform Username node](https://docs.pingidentity.com/auth-node-ref/8.1/platform-username.html) 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](#mfa-webauthn-profile-encryption) 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:

   * [Page node](https://docs.pingidentity.com/auth-node-ref/8.1/page.html) (v2.0)

   * [Username Collector node](https://docs.pingidentity.com/auth-node-ref/8.1/am-only/username-collector.html)

   * [Password Collector node](https://docs.pingidentity.com/auth-node-ref/8.1/am-only/password-collector.html)

   * [WebAuthn Authentication node](https://docs.pingidentity.com/auth-node-ref/8.1/webauthn-authentication.html) (v2.0)

   * [Data Store Decision node](https://docs.pingidentity.com/auth-node-ref/8.1/data-store-decision.html)

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

   ![A tree for WebAuthn conditional UI](_images/auth-tree-webauthn-conditional-ui.png)

5. On the [Username Collector node](https://docs.pingidentity.com/auth-node-ref/8.1/am-only/username-collector.html):

   * Add the following values to the Autocomplete Values field:

     `username`\
     `webauthn`

6. On the [WebAuthn Authentication node](https://docs.pingidentity.com/auth-node-ref/8.1/webauthn-authentication.html):

   * 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](_images/webauthn-conditional-ui-login.png)

## 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](#mfa-webauthn-profile-encryption) 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](https://docs.pingidentity.com/auth-node-ref/8.1/data-store-decision.html)

   * [Page node](https://docs.pingidentity.com/auth-node-ref/8.1/page.html)

   * [Username Collector node](https://docs.pingidentity.com/auth-node-ref/8.1/am-only/username-collector.html)

   * [Password Collector node](https://docs.pingidentity.com/auth-node-ref/8.1/am-only/password-collector.html)

   * [WebAuthn Registration node](https://docs.pingidentity.com/auth-node-ref/8.1/webauthn-registration.html)

   * (Optional) [Scripted Decision node](https://docs.pingidentity.com/auth-node-ref/8.1/scripted-decision.html)

     By default, the [WebAuthn Registration node](https://docs.pingidentity.com/auth-node-ref/8.1/webauthn-registration.html) stores the tree's shared state variable `username` on the device. During authentication, this value later identifies the user.

     Use a [Scripted Decision node](https://docs.pingidentity.com/auth-node-ref/8.1/scripted-decision.html) to customize the display name or string to be saved in the shared state.

     Script to set the display name

     * Next-generation

     * Legacy

     ```javascript
     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");
     ```

     ```javascript
     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.](_images/fr-go-reg-tree.png)

   If you *do not* use the [Scripted Decision node](https://docs.pingidentity.com/auth-node-ref/8.1/scripted-decision.html), connect the [Data Store Decision node](https://docs.pingidentity.com/auth-node-ref/8.1/data-store-decision.html) `True` output directly to the [WebAuthn Registration node](https://docs.pingidentity.com/auth-node-ref/8.1/webauthn-registration.html).

5. If you use the [Scripted Decision node](https://docs.pingidentity.com/auth-node-ref/8.1/scripted-decision.html):

   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](https://docs.pingidentity.com/auth-node-ref/8.1/webauthn-registration.html):

   1. Enable Username to device.

   2. If you *do not* use the [Scripted Decision node](https://docs.pingidentity.com/auth-node-ref/8.1/scripted-decision.html), add `userName` in the Shared state attribute for display name field.

   3. If you use the [Scripted Decision node](https://docs.pingidentity.com/auth-node-ref/8.1/scripted-decision.html), 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](#mfa-webauthn-profile-encryption) 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](https://docs.pingidentity.com/auth-node-ref/8.1/webauthn-authentication.html) to your tree.

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

   ![A tree for usernameless device authentication.](_images/fr-go-auth-tree.png)

5. On the [WebAuthn Authentication node](https://docs.pingidentity.com/auth-node-ref/8.1/webauthn-authentication.html), 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.](_images/fr-go-registered-accounts.png)

   In this example, the user's full name and email address appear. The [Scripted Decision node](https://docs.pingidentity.com/auth-node-ref/8.1/scripted-decision.html) 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](https://docs.pingidentity.com/auth-node-ref/8.1/webauthn-registration.html) 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:

   ```bash
   $ 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](../security/secret-stores.html#file-system-secret-volumes).

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`:```javascript
     var attestationLevel = transientState.get("webauthnAttestationType");
     ``` |

   * Save your changes.

     For more information on the available properties, see [WebAuthn Registration node](https://docs.pingidentity.com/auth-node-ref/8.1/webauthn-registration.html).

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.](_images/webauthn-trust-store.png)

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.](_images/webauthn-trust-store-mappings.png)

13. Save your changes.

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