Skip to main content
Passkeys let a user sign in with biometrics, a PIN, or a security key instead of a password. Guile exposes both flows through the same challenge endpoints OTP uses.

What you do first

  1. Confirm the browser supports WebAuthn (Chrome/Edge 108+, Safari 16+, Firefox 119+) before you offer passkeys.
  2. Register at least one passkey for the user (POST /auth/passkeyRegistrationOptions, then create the credential, then POST /auth/passkeys).
  3. Create a challenge with POST /auth/challenges and method: "passkey".
  4. Run WebAuthn on the device, then verify with POST /auth/verifiedChallenges and the assertion.
  5. Store the access and refresh tokens the same way you would for OTP.
Label usernameless as “Sign in with passkey” and username-first as “Use passkey”. Offer OTP on the same challenge endpoints when passkeys are unavailable. Registration creates a discoverable credential (resident key) so usernameless sign-in works. Options use human-readable names (relyingParty, publicKeyCredentialParameters, algorithm values like ES256), map those to WebAuthn COSE ids in your client. Supported algorithms: ES256 (preferred for broad device support), RS256, EdDSA, ES384, ES512.

States that matter

Omit the identifier. The API returns an empty allowCredentials list; the browser discovers passkeys on the device.

Username-first

Send phoneNumber or emailAddress on the challenge. Use this when the user prefers to enter an identifier, or as a fallback when usernameless fails. All Guile passkeys are discoverable (residentKey: "required"). Users can list and delete passkeys, and register more than one device.

When a call fails

Failures come back as problem documents. Open the type link for the cause, the fix, and whether retrying is safe. Common ones on this path: