Help users adopt passkeys more seamlessly

Published: May 09, 2025

Passkeys offer strong, phishing-resistant authentication. However, getting users to adopt them can introduce friction. With automatic passkey creation you can create passkeys for your users at the right moment, as long as they already have a password saved for your site. Conditional Create, which enables automatic passkey creation, is part of the WebAuthn specification.

How it works

To help users adopt passkeys more conveniently, use a WebAuthn API feature called Conditional Create. Conditional Create lets your site request a passkey for the user without requiring any action from them.

This flow works when the following conditions are met:

  • The user has a saved password in their default password manager.
  • The password was used recently. Ideally, call Conditional Create immediately after a successful password-based login.

If both conditions are met, you can request the password manager to create a passkey for the user by calling Conditional Create. After successfully creating the passkey, the user is notified depending on the password manager.

Passkey request flow with conditional create.

Compatibility

Conditional Create is supported by Safari on macOS and iOS, as well as Chrome on desktop.

Implement Conditional Create

Automatic passkey creation is based on a WebAuthn API feature called Conditional Create. These are regular WebAuthn create() requests with the mediation parameter set to "conditional" which works similarly to passkey autofill for get() requests.

Use Conditional Create after the user signs in with a password. Whether the creation succeeds depends on the password manager and certain conditions being met. These conditions can vary by password manager and may change over time. For example, in Chrome with Google Password Manager (GPM), the user must have recently signed in using a saved password for the site.

If the browser successfully creates the passkey, it returns a public key credential. Send this credential to your backend to complete registration and enable future authentication.

Feature detection

You can determine whether Conditional Create is available on the browser by invoking PublicKeyCredential.getClientCapabilities(). See if a returned object contains true for the conditionalCreate property.

if (window.PublicKeyCredential && PublicKeyCredential.getClientCapabilities) {
  const capabilities = await PublicKeyCredential.getClientCapabilities();
  if (capabilities.conditionalCreate) {
    // Conditional create is available
  }
}

If getClientCapabilities is unavailable, then Conditional Create is also unavailable.

Create a passkey conditionally

To perform an automatic passkey creation, invoke navigator.credentials.create() but with mediation: "conditional" like so.

const cred = await navigator.credentials.create({
  publicKey: options,
  // Request conditional creation
  mediation: 'conditional'
});

You should use automatic passkey creation immediately after your user signs in to have the best chance to meet the password manager criteria for automatic creation.

You can send the resulting public key credential to the server to verify and register the passkey. On the server, make sure that the user is signed in.

Caveats

Conditional Create by itself is not difficult to implement, but there are several caveats when actually integrating this feature into an existing system.

Ignore user presence and user verification on the server

The registration response returns both "User Presence" and "User Verified" as false, so the server should ignore these flags during credential verification.

Abort ongoing WebAuthn call before performing an automatic passkey creation

When the RP expects the user to sign in with either a passkey or a password, performing a conditional get is the best choice. This may cause the conditional get call to be canceled before performing a conditional create.

To do so, you need to use AbortController and call .abort().

// To abort a WebAuthn call, instantiate an AbortController.
const controller = new AbortController();

const cred = await navigator.credentials.get({
  publicKey: options,
  signal: controller.signal,
  // Request conditional get
  mediation: 'conditional'
});

// Abort the call
controller.abort();

Ignore the exceptions gracefully

When a conditional passkey creation is performed, there are a few cases you should ignore exceptions:

  • InvalidStateError: A passkey already exists in the passkey provider (Don't forget to specify excludeCredentials).
  • NotAllowedError: Creating a passkey doesn't meet the condition.
  • AbortError: The WebAuthn call is aborted.

Displaying errors in these cases may confuse the user since the browser handles them silently: it shows a notification only on success, and failures don't trigger visible messages.

Signal when registering a passkey fails

When a passkey is created but failed to be registered on the server, the user will experience a failing sign-in attempt. This can happen when the list of passkeys are inconsistent between the passkey provider and the server.

To avoid such circumstances, use the Signal API to keep them consistent.

Upgrade from passwordless sign-ins is not supported

At this point, creating a passkey conditionally is gated behind the user entering a valid password. This means passwordless sign-in approaches such as magic links, phone number verification or identity federation won't meet the condition.

Summary

Automatic passkey creation can accelerate passkey adoption on your website, helping users getting your website's users to make a transition from passwords to a more secure authentication method.

To learn more about passkeys, start from Passwordless login with passkeys.