Implementing Passkey Authentication

Implementing Passkey Authentication

Passkeys let your users sign in without a password, using their device’s biometrics (Touch ID, Windows Hello) or a hardware security key. Skycloak ships this as a built-in Recipe — a pre-built, realm-scoped configuration you turn on from the dashboard. There’s no custom authenticator to write and no separate frontend/backend to build; this tutorial walks through enabling it and understanding what it changes under the hood.

What Are Passkeys?

Passkeys are the WebAuthn/FIDO2 standard applied to everyday login:

  • A public/private key pair is generated on the user’s device; only the public key is ever sent to Keycloak
  • Signing in proves possession of the private key (via biometrics or a PIN-protected security key) — there’s no shared secret that can be phished, leaked, or reused across sites
  • Faster than typing a password, and nothing for the user to remember or rotate

Prerequisites

  • A running Keycloak cluster with at least one realm
  • Workspace Owner or Admin role
  • Users’ browsers/devices should support WebAuthn (all current major browsers and OS platform authenticators do)

How the Recipe Works

The Passkeys recipe is realm-scoped — you apply it once per realm, and it’s tracked independently per cluster/realm. Turning it on does three things to that realm:

  1. Enables the webauthn-register-passwordless required action, so users can register a passkey.
  2. Builds a separate browser-passkey authentication flow — identity-first (username first, then passkey), with password and conditional OTP kept as a fallback for anyone without a registered passkey yet. Your existing browser flow is left untouched.
  3. If you check “Enforce for all users”, retro-applies the required action to every existing user in the realm, so they’re prompted to register a passkey on their next login.

After applying, Skycloak also best-effort re-applies your realm’s login theme, since the new identity-first flow renders a couple of pages a previously generated custom theme might not include yet. This step is non-blocking — if it fails, the recipe still completes and you can re-apply branding manually from the Branding page.

Step 1: Open Recipes

  1. Select your cluster and realm in the sidebar’s context stack
  2. Click “Recipes” in the sidebar — this opens the realm’s Configuration Recipes page, a grid of pre-built configuration cards

Step 2: Start the Passkeys Recipe

  1. Find the “Passkeys” card (category: Authentication, difficulty: Easy, about 1 minute)
  2. Click “Start Recipe”

Step 3: Configure and Enable

  1. You’ll land on a single-step wizard headed “Enable passkeys”
  2. Optional: check “Enforce for all users” — if checked, every existing user in the realm gets prompted for passkey registration on their next login. Leave it unchecked if you’d rather let users opt in gradually.
  3. Click “Enable” (or “Enable & enforce” if you checked the box)

The recipe applies immediately — no separate “apply” step or propagation delay to wait on.

Step 4: Test the Flow

  1. Open an incognito window and go to your realm’s login page (or a connected application)
  2. New user / first login after enabling: after entering a username, the user is prompted to register a passkey (or complete password + OTP if their device doesn’t support WebAuthn)
  3. Returning user with a registered passkey: enters their username, then completes sign-in with Touch ID, Windows Hello, or a security key — no password step at all
  4. Existing user under “Enforce”: on next login, they’re walked through registering a passkey via the webauthn-register-passwordless required action before they can continue

Passkeys vs. the MFA (WebAuthn) Recipe

Don’t confuse this with the separate MFA recipe (mfa-webauthn) — they solve different problems and compose well together:

Passkeys recipe MFA (WebAuthn) recipe
Role of WebAuthn Primary factor, replaces the password Second factor, on top of the password
Flow changes Builds a new browser-passkey identity-first flow Adds to the stock browser flow, no rebuild
Login experience Username, then passkey (password is a fallback) Username + password, then WebAuthn/TOTP challenge

Enabling both lets users who’ve registered a passkey sign in passkey-first, while users without one still get username/password plus a second factor as a fallback path.

Troubleshooting

Passkey prompt doesn’t appear:

  • Confirm the webauthn-register-passwordless required action shows as enabled for the realm
  • Check the user’s browser and device support WebAuthn (most modern browsers and OS platform authenticators do; older browsers may not)

Login page looks off after enabling:

  • The post-enable theme reapply is best-effort — if your realm uses a custom theme, revisit the Branding page and re-apply it manually if anything looks inconsistent

Users without a passkey-capable device get stuck:

  • The identity-first flow keeps password + conditional OTP as a fallback by default, so nobody is locked out — if a user reports otherwise, check whether “Enforce” was applied and whether their account has a password credential set

Best Practices

  • Roll out gradually: apply without “Enforce” first, let early adopters register passkeys, then enforce once you’re confident in the flow
  • Communicate before enforcing: users forced into a required action mid-login can be caught off guard — a heads-up email helps
  • Test across devices: verify the flow on at least one mobile and one desktop browser before enforcing realm-wide

Next Steps

Last updated on