Prerequisites
Before you start, make sure you have:- A Prelude account with access to Prelude Auth
- An Application ID (
appID): see Applications - Your Management API key for backend calls
- A frontend served over HTTPS, or
http://localhost:<port>for local development, the WebAuthn API refuses any other origin
Set up passkey authentication
Configure the WebAuthn Relying Party identity for your app. The RP identity is shared across every passkey ceremony, changing it after credentials are registered invalidates them at the authenticator layer, so set it once per environment.1
Create a passkey configuration
2
Declare verify_passkey on the step-up configuration
Add the step key to your step-up configuration and reference it from any scope whose challenge should require a passkey.A registered passkey shows up on the user as an identifier of type
passkey, so direct-mode entries select on it via identifier_types like any other identifier.To express a passkey-or-OTP fallback, list two direct entries on the same scope, the passkey-gated one first, the OTP fallback second. The runtime serves the first one whose identifier types the user holds:Enable passwordless login (optional)
Setlogin_enabled: true on the PasskeyConfig to opt the app into primary-factor passkey sign-in. While the flag is on, registration also requests a discoverable credential (residentKey: required) so the resulting passkey shows up in the browser’s autofill chip.
passkey_registration_failed after the flag flips on.
Enterprise authenticator policy (optional)
Restrict registration to specific authenticator models via the AAGUID allowlist / blocklist on the PasskeyConfig. Pairs withattestation_preference: "direct" or "enterprise", with "none" most authenticators return an all-zeros AAGUID and the allowlist matches nothing.
Subscribe to passkey lifecycle events (optional)
Three webhook events surface passkey activity for audit and user notifications:
Subscribe via the existing webhook configuration:
Surface passkey state in access tokens (optional)
The custom-claims pipeline exposes ahas_passkey template input. Map it on your app’s claims configuration to let your frontend decide whether to prompt the user to enrol: