Skip to content

Using passkey autofill to support passkeys alongside passwords

Passkey autofill essentially tells the browser to bypass a login form and use a passkey if one exists on the device. The moment the user interacts with the login form, the browser will prompt them to sign in using the passkey.

To use autofill, call authenticatePasskey with the autofill: true property. Call this on page load so it’s ready by the time the user interacts with your login form. e.g.

import { authenticatePasskey, isAuthenticationSuccess } from "@passlock/client";
document.addEventListener('DOMContentLoaded', async () => {
try {
// The promise will be pending until the user interacts
// with the login form
const result = await authenticatePasskey({
tenancyId,
autofill: true
});
await submitCodeToBackend(result.code);
} catch (e) {
// TODO use one of the type guards to narrow the error
console.error(e);
}
})

You also need to include the webauthn token in the autocomplete attribute on the relevant login form field e.g.

<input type="text" name="username" autocomplete="username webauthn" />

We use autofill for our console app. If you’ve registered a passkey your device should prompt you to authenticate with it, instead of going through the usual login flow:

Passkey autofill in action

Many web apps allow users to sign in via different mechanisms e.g. social, passwords, one-time codes etc. You might choose to present users with a login screen in which they can select how they want to log in:

Primary two-step authentication using passkeys Primary two-step authentication using passkeys

This can present a challenge for the user as they might not remember which mechanism they used during signup. Did they register a passkey or not? If autofill is employed, the browser/device will decide for them, prompting them to use a passkey if one exists on the device.

Browser support for autofill is somewhat flaky. Additionally you need to ensure a couple of things happen before the user interacts with the login form:

  1. The relevant client-side JS has loaded
  2. The device has had time to check for registered passkeys

You can work around these issues by waiting for the JS to load before enabling the login form. Alternatively you can display the form but wait for the code to load then programmatically add the webauthn token to the relevant field’s autocomplete attribute.

A user might register a passkey then delete the server-side component e.g. via a “my passkeys” page in your app. They will end up with a passkey on their device, which the device will use for autofill, but there will be no corresponding record in your backend systems. You need to account for this scenario and wherever possible use our local passkey removal function to align your backend records with the user’s local device.

Tech-savvy users should have no trouble with autofill, however some users find it confusing. They’re trying to enter their credentials but the browser tries to fill the username field with a passkey.

You’ll need to decide if the benefits of rapid, frictionless passkey login outweigh the potential drawbacks and usability issues. If you choose not to adopt autofill, two-step login can be a more reliable and intuitive flow for many users.