WebAuthn Conditional UI: Technical Explanation and Implementation

With the rapid adoption of passkeys (and the underlying WebAuthn protocol), authentication has become more secure and user-friendly for many users. One of the standout advancements of passkeys has been the integration of Conditional UI, often referred to as "passkey autofill" or Conditional Mediation (in the following, we stay with the term Conditional UI).

Despite its recent introduction and ongoing adoption by browsers, there’s a noticeable gap in technical documentation and implementation advice for Conditional UI. This article aims to bridge that gap by explaining what Conditional UI is, how it works, and how to tackle common challenges during its implementation.

What Is Conditional UI?

Conditional UI represents a new mode for passkeys/WebAuthn login processes. It selectively displays passkeys in a user interface (UI) only when a user has a discoverable credential (resident key), which is a type of passkey registered with the relying party (the online service) stored in their authenticator of a device (e.g., laptop, smartphone). The passkeys are displayed in a selection dropdown that is mixed up with auto-filled passwords, providing a seamless transition between traditional password systems and advanced passkey authentication, as users see both in the same context. This intelligent approach ensures that users aren't overwhelmed with unnecessary options and can navigate the login process more seamlessly.

The foundation of Conditional UI is built on three main pillars:

  1. Respect user privacy: Ensuring user privacy by preventing disclosure of available credentials or lack of user consent to reveal these credentials.
  2. Great user experience even if no passkey exists: Empowering relying parties to implement WebAuthn opportunistically, ensuring user experience remains good even if passkeys are not available.
  3. Smooth transition from passwords to passkeys: Combining passkeys with password-based authentication to smooth the transition towards passwordless authentication methods, capitalizing on users' familiar UX paradigms.

Conditional UI Benefits and Drawbacks

Benefits

Drawbacks

How Does Conditional UI Work?

In the following, we provide a step-by-step breakdown of the single steps of an entire Conditional UI flow:

conditional UI

In general, the Conditional UI process flow can be partitioned into two phases. During the page load phase, conditional UI logic happens in the background, while in the user operation phase, the user has to do something actively.

  1. Conditional UI availability checks: The client (browser) calls the isConditionalMediationAvailable() function to detect if the current browser/device combination supports Conditional UI.
    Only if the response is true does the process continue; otherwise, the Conditional UI process is aborted.
  2. Call the conditional UI endpoint: Next, the client calls the server Conditional UI endpoint in order to retrieve the PublicKeyCredentialRequestOptions.
  3. Receive PublicKeyCredentialRequestOptions: The server returns the PublicKeyCredentialRequestOptions which contain the challenge and more WebAuthn server options (e.g., allowCredentials, extensions, userVerification).
  4. Start the local authentication: By calling credentials.get() with the received PublicKeyCredentialOptions and the mediation property is set to be “conditional, the process for the local authentication on the device starts.
  5. Show autofill selection: The autofill menu for passkeys pops up. The specific styling is dependent on the browser and device (e.g., some require the user to place the cursor in the input field, and some automatically display the menu on page load; see below).
  6. Local user authentication: The user selects the passkey from the autofill menu that they want to use and authenticate via the authentication dialog of their device (e.g., via Face ID, Touch ID, Windows Hello).
  7. Send authenticator response to server: If the local user authentication was successful, the authenticator response is sent back to the server.
  8. User is logged in and redirected: Once the server receives the authenticator response, it validates the signature against the corresponding user account’s public key in the database. If the verification is successful, the user is granted access, logged in, and redirected to the logged-in page.

By following this process flow, Conditional UI offers a seamless and user-friendly authentication experience.

Technical Requirements for Conditional UI

General

To get Conditional UI working, some general aspects need to be considered:

Client-Side

To get Conditional UI working on the client side, the following requirements must be fulfilled:

Server-Side

To get Conditional UI working, some requirements on the server side must be fulfilled as well:

Practical Coding Tips

Since the official rollout of Conditional UI in late 2022 and earlier beta versions, we’ve been testing and working extensively with it. In the following, we want to share practical tips that helped during the implementation of Conditional UI with you.

A useful tool to debug WebAuthn registration and authentication responses is the passkeys debugger.

Full Conditional UI Example

A full, minimalistic code example for a Conditional UI method would look like this:

HTML
 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Conditional UI</title>
</head>
<body>

<input type="text" id="username" autoComplete="username webauthn" />
<button onclick="passkeyLogin()">Login via passkey</button>

</body>
</html>


Browser Compatibility Check

Implement Conditional UI detection that ensures that Conditional UI is only employed when the current device/browser combination supports it. This should work without presenting user-visible errors in the absence of Conditional UI support. Incorporating the isConditionalMediationAvailable() method within the user interface addresses this concern. If Conditional UI support is given, the Conditional UI login process can be started.

JavaScript
 
// source: https://developer.mozilla.org/en-US/docs/Web/API/PublicKeyCredential/isConditionalMediationAvailable#examples

// Availability of `window.PublicKeyCredential` means WebAuthn is usable.
if (
  window.PublicKeyCredential &&
  PublicKeyCredential.isConditionalMediationAvailable
) {
  // Check if conditional mediation is available.
  const isCMA = await PublicKeyCredential.isConditionalMediationAvailable();
  if (isCMA) {
    // Call WebAuthn authentication start endpoint

    let options = await WebAuthnClient.getPublicKeyRequestOptions();

    const credential = await navigator.credentials.get({
      publicKey: options.publicKeyCredentialRequestOptions,
      mediation: "conditional",
    });
    /*
    ...
    */
  }
}


WebAuthn Autocomplete Token in Input Fields

The input field should receive a “webauthn” HTML autofill token. This signals the client to populate passkeys to the ongoing request. Besides passkeys, other autofill values might be showcased as well. These autofill tokens can be paired with other existing tokens, e.g.:

HTML
 
<label for="name">Username:</label>
<input type="text" name="name" autocomplete="username webauthn">
<label for="password">Password:</label>
<input type="password" name="password" autocomplete="current-password webauthn">


Mediation Property in WebAuthn API Get Call

To retrieve available passkeys after having received the PublicKeyCredentialRequestOptions object, the navigator.credentials.get() function should be called (which serves both passkeys and passwords). The PublicKeyCredentialRequestOptions object needs to have the mediation parameter set to “conditional” to activate Conditional UI on the client.

JavaScript
 
const credential = await navigator.credentials.get({
  publicKey: options.publicKeyCredentialRequestOptions,
  mediation: "conditional"
});


Cancellation of Conditional UI Flow

If there's no available passkey, or the user neglects the suggested passkeys and enters their email, the Conditional UI flow is stopped. This underscores the importance of always supporting the standard passkey / WebAuthn login via a modal as well.

A critical point to emphasize here is the potential need to halt an ongoing Conditional UI request. Contrary to modal experiences, autofill dropdowns lack a cancellation button. As per WebAuthn's design, only a single active credential request should be in progress at any given moment. The WebAuthn standard suggests utilizing an AbortController to cancel a WebAuthn process, applicable to both regular and Conditional UI login processes (see WebAuthn's Docs for details).

The Conditional UI login process gets activated as soon as a user lands on the page. The initial task should be to create a globally-scoped AbortController object. This will act as a signal for your client to terminate the autofill request, especially if the user decides to do the regular passkey login process. Reassure that the AbortController can be invoked by other functions and is reset if the Conditional UI process has to restart. Employ the signal property within the navigator.credentials.get() call, incorporating your AbortController signal as its value. This signals to the passkey / WebAuthn function that the request must be halted if the signal gets aborted. Remember to set up a fresh AbortController each time you trigger Conditional UI. Using an already-aborted AbortController will lead to an instant cancellation of the passkey / WebAuthn function. The remaining steps align with a regular passkey login process. In the following, you see a code example of the mentioned steps:

HTML
 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Conditional UI</title>
</head>
<body>

<input type="text" id="username" autoComplete="username webauthn" />
<button onclick="passkeyLogin()">Login via passkey</button>



</body>
</html>


In the absence of Conditional UI support, direct users towards the regular passkey login process. Offering this path is important for users relying on hardware security keys (e.g., YubiKeys) or those compelled to use non-resident keys / non-discoverable credentials due to authenticator constraints.

Conditional UI in Native Apps

When you develop a native app, e.g., for iOS or Android, Conditional UI works as well. It doesn’t matter if you implement it natively in Flutter, Kotlin, or Swift or if you decide to go with Chrome Custom Tabs CCT or SFSafariViewController or SFAuthenticationSession / ASWebAuthenticationSession. Both approaches support Conditional UI.

Conditional UI Examples in Different Devices/Browser

To illustrate how Conditional UI looks like for the end user, we added several screenshots of a Conditional UI autofill menu using https://passkeys.eu.

Conditional UI in Windows 11 (22H2) + Chrome 118

passkeys demo

Conditional UI in macOS Ventura (13.5.1) + Chrome 118

try passkey loginConditional UI in macOS Ventura (13.5.1) + Safari 16.6

ConditionalUI enhances WebAuthn by enabling a passkey autofill for users, improving the UX and authentication flow. This article guides you through its implementation.Conditional UI in Android 13 + Chrome 118

Conditional UI in Android 13 + Chrome 118

Conditional UI in iOS 17.1 + Safari 17.1

Conditional UI in iOS 17.1 + Safari 17.1Conclusion

Passkeys, with its Conditional UI/passkey autofill capability, are the new way to authenticate online. As we transition to an era where passwords are more and more replaced by passkeys, the need for robust and user-friendly transition mechanisms is undeniable. We hope this article has helped you to understand how to correctly implement Conditional UI, handle the transition process, and which aspects to pay special attention to.

 

 

 

 

Top