Skip to main content

Passkeys & WebAuthn

Passkeys provide passwordless authentication using the FIDO2/WebAuthn standard (WebAuthn is the browser API behind passkeys; FIDO2 covers the authenticators that hold them). The user authenticates with a biometric (fingerprint, face) or hardware security key, and your server never handles a shared secret. The private key never leaves the device; LumoAuth stores only the public key and verifies a signed challenge at login.


What Are Passkeys?​

Passkeys are cryptographic credentials stored on the user's device. They use public-key cryptography — the private key never leaves the device, and the public key is stored in LumoAuth. Authentication happens via a challenge-response, which makes passkeys:

  • Phishing-resistant — bound to the specific origin (domain).
  • Free of shared secrets — nothing reusable to steal from the server.
  • Biometric-backed — require fingerprint, face, or PIN to use.
  • Cross-device — can sync across devices via platform credential managers.

Supported Credential Types​

TypeExamplesUse Case
Platform AuthenticatorsTouch ID, Face ID, Windows HelloBuilt into the device
Roaming AuthenticatorsYubiKey, Titan Security KeyUSB/NFC hardware keys
Synced PasskeysiCloud Keychain, Google Password Manager, 1PasswordCross-device passkeys

How It Works​

Registration (Enrollment)​

  1. The user starts from Secure your account after sign-in (where a passkey is the recommended first factor whenever the browser reports Touch ID, Face ID, Windows Hello or an Android screen lock), or from Sign-in & security → Add a sign-in method.
  2. They click Create a passkey.
  3. The browser prompts for biometric verification, a screen lock or a security key.
  4. A new public-private key pair is generated on the device; the private key never leaves it.
  5. LumoAuth verifies the attestation and stores the public key.
  6. The passkey is named after the device and browser, for example "Mac – Chrome" or "iPhone – Safari". Users can rename it later.

Passkeys are created as discoverable credentials (residentKey: required), and the request lists the user's existing passkeys in excludeCredentials so the same authenticator is not registered twice.

Authentication​

  1. User enters their email (or clicks Sign in with a passkey).
  2. LumoAuth sends a cryptographic challenge to the browser.
  3. Browser prompts for biometric verification or PIN.
  4. The private key on the device signs the challenge and marks it user verified.
  5. LumoAuth verifies the signature with the stored public key and rejects the assertion if the user was not verified.
  6. Login is complete — no password needed.

User verification is required​

A passkey is a complete sign-in on its own, so LumoAuth asks for user verification (UV) on every registration and every sign-in. UV means the authenticator confirmed who is present (biometric or PIN), not just that something was present (a touch, called user presence or UP). Concretely:

  • Registration uses userVerification: "required", so a credential can only be created with a PIN or biometric. A security key without a PIN prompts the user to set one.
  • Sign-in uses userVerification: "required", and the server checks the UV flag in the signed assertion. An assertion produced by a bare touch is rejected.
  • Clients cannot downgrade this; the request options are generated server-side.
  • Passkey user lookups are scoped to the organization whose login page or custom domain the ceremony runs on, so a credential registered in one organization cannot sign in to another.

What users see: Touch ID, Face ID, Windows Hello, Android biometrics or their password-manager prompt as usual; on a hardware key, a PIN prompt followed by a touch.

Standard

WebAuthn Level 2 (W3C) / FIDO2. The userVerification option distinguishes user presence (UP: someone touched the authenticator) from user verification (UV: the authenticator checked a PIN or biometric). When a passkey replaces the password, only UV proves that the account owner is the one signing in, so the relying party must request required and check the UV flag in the assertion's authenticator data. WebAuthn: user verification


Configuration​

Enable Passkeys​

Navigate to Security → Sign-in settings at:

/orgs/{orgId}/portal/settings/authentication

In the Identity methods section, turn on Passkeys & biometrics and click Save changes. Two sub-options sit below the switch: Permit platform-bound biometrics (Windows Hello, macOS Touch ID) and Require FIDO-certified authenticators.

The Identity methods section with the Passkeys & biometrics switch and its sub-options

Settings​

SettingDescription
Passkeys & biometrics (passkey_enabled)Users can register passkeys in account settings and sign in with them. Off means passkey sign-in is refused at the WebAuthn endpoints ("Passkey sign-in is not enabled for your organization. Sign in another way."), not just hidden on the login page, and the account page refuses new passkeys (403 passkeys_disabled) unless the MFA policy (multi-factor authentication) allows passkeys as a factor.
Require FIDO-certified authenticatorsOnly authenticators whose AAGUID appears in the FIDO Metadata Service cache with a certification and no compromise report may register. Applies to every registration path: the account page and the MFA API (400 with "This authenticator is not FIDO certified…").

Passkeys used as a second factor are governed by the MFA policy's allowed factors, not by Passkeys & biometrics, so turning passkey sign-in off does not lock out users who verify with a passkey as their second step.

User verification is not a setting: it is always required, for every organization.


WebAuthn Routes​

LumoAuth exposes two distinct sets of WebAuthn endpoints — one for logging in with an existing passkey, and one for enrolling a passkey from account settings. Both follow the WebAuthn specification and are driven by the portal's navigator.credentials calls; you normally do not call them directly.

Login (passwordless sign-in):

POST /login/webauthn/options → Generate authentication options (challenge)
POST /login/webauthn/result → Verify the signed assertion and sign the user in

Account enrollment (add/remove a passkey):

POST /account/security/passkey/options → Generate registration options
POST /account/security/passkey/register → Complete registration
DELETE /account/security/passkey/{id} → Remove an enrolled passkey

There is also an OAuth-flow passkey login endpoint used during the authorization flow:

GET /orgs/{orgId}/api/v1/oauth/passkey-login

User Experience​

Enrolling a Passkey​

From Secure your account (/auth/secure-account) or the account security page (/account/security → Add a sign-in method):

The Sign-in & security page with the Add a sign-in method menu offering Passkey

  1. Click Create a passkey (from Add a sign-in method, choose Passkey).
  2. Complete the biometric, screen-lock or security-key prompt.
  3. The passkey appears in Sign-in & security with its default name, the Strongest tier label and the date it was added.

If the user cancels the OS prompt, the screen stays where it was, without an error, and shows Try again next to the other ways to secure the account. A user who already holds a sign-in method must confirm it is them before adding a passkey (see step-up).

Logging In with a Passkey​

On the login page:

  1. Click Sign in with a passkey (or start typing an email).
  2. The browser shows available passkeys.
  3. Select a passkey and verify with biometrics.
  4. Login proceeds — no password or MFA needed.

Managing Passkeys​

Users manage passkeys under Sign-in & security (/account/security), together with their other sign-in methods:

The Sign-in & security page listing the user's sign-in methods under Two-step verification

  • See each passkey with its name, when it was added and when it was last used.
  • Rename a passkey or Make default.
  • Remove… a passkey. This needs a fresh verification with a different sign-in method when the user has one, and is refused when it is the user's last method and the organization requires MFA.
  • Add another passkey.

Passkeys and the MFA policy​

Passkeys are the strongest factor (tier 1, "Strongest") in the MFA policy and the first recommendation during enrollment.

  • Passwordless (default). With the policy key passwordless_passkey on (portal: A passkey counts as both factors), signing in with a passkey that performed user verification satisfies both factors: no password and no second prompt. Tokens carry amr: ["hwk", "user", "mfa"] and acr: urn:lumoauth:acr:mfa:phr.
  • Passwordless off. A passkey sign-in counts as the first step only, and the user is asked for a second factor like any other sign-in.
  • As a second factor. After a password, the MFA challenge can use a passkey: the browser shows its passkey prompt and the user confirms with biometrics. Assertions are restricted to the user's own passkeys.
  • Step-up. Applications can demand a phishing-resistant sign-in with acr_values=urn:lumoauth:acr:mfa:phr (or phr); see ACR and AMR.

If the organization removes passkey from allowed_factors, passkeys are not offered for enrollment and do not count at sign-in.


Security Benefits​

FeaturePasswordsPasskeys
Phishing riskHigh — can be entered on fake sitesNone — bound to origin
Server breachHashed passwords can be crackedOnly public keys stored
Replay attacksPossibleImpossible — challenge-response
User effortRemember complex passwordsTouch fingerprint sensor
Cross-siteSame password often reusedUnique per site

Browser Support​

Passkeys are supported in:

  • Chrome 108+ (Windows, macOS, Android)
  • Safari 16+ (macOS, iOS)
  • Firefox 122+ (Windows, macOS, Linux)
  • Edge 108+ (Windows, macOS)

For older browsers, passkey options will not appear and users can fall back to password + MFA authentication.


Troubleshooting​

  • "Sign-in failed" right after a successful touch on a security key. The key has no PIN, so it could not perform user verification. Set a PIN on the key (in the browser's or OS security-key settings) and try again; registration of a new key will ask for one automatically.
  • Registration prompt asks to create a PIN. Expected on keys without one; user verification is mandatory.
  • A passkey works on one organization's login page but not another's. Passkeys are tied to the organization they were registered in. Register a separate passkey per organization.
  • Older automation or custom clients that sent userVerification: "discouraged". The server ignores client preferences; update the client to allow the UV prompt.

Standards used on this page​

Plain nameStandard
Passkeys (WebAuthn and FIDO2)W3C Web Authentication and FIDO Alliance CTAP

See the standards reference for what each one covers and how LumoAuth uses it.