Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Demo: passkey (WebAuthn) login

Location: contrib/demo/passkey/

Starts a single ahdapa instance configured for WebAuthn passkey authentication using static users — no FreeIPA or Kerberos infrastructure is required. On first run only password login is available; a registration helper page lets you create a passkey credential and add it to the users file.

What it shows

  • WebAuthn credential registration — a standalone HTML page served by the demo instance walks through the navigator.credentials.create() call and generates the passkey:<credentialId>,<COSE_Key> line for the users file.
  • Passkey login — after adding the credential to the overlay file, entering a username on the login page triggers the navigator.credentials.get() prompt instead of (or before) the password field.
  • Overlay-based credential management — a gitignored overlay file is merged with the base users file at startup. The overlay takes precedence over same- username entries in the base file, so passkey credentials can be added without modifying the tracked users.toml.
  • RP ID scoping — the demo uses RP ID localhost. Passkeys registered with this configuration are tied to localhost and will not work on any other origin.

Prerequisites

  • ahdapa binary — the script looks in $PATH first (resolved to its full path), then target/release/ahdapa, then target/debug/ahdapa, and falls back to cargo build if none is found.
  • npm — for building the WebUI dist/ directory on first run.
  • A browser that supports WebAuthn (all modern browsers do).
  • Port 8080 free.
  • For hardware security key testing: a FIDO2-capable key (YubiKey, SoloKey, etc.)
  • For virtual authenticator testing: Chrome DevTools → Application → Web Authentication → Enable virtual authenticator.

Running

contrib/demo/passkey/run.sh

On first run (when no webui/dist/ directory and no pre-built binary exist) the script builds the WebUI and the binary, then starts ahdapa. If a binary is already installed or built, it is used directly and the build step is skipped. The selected binary path is printed before launch:

==> Building WebUI (first run)…
Using binary: /home/user/ahdapa/target/release/ahdapa

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  PASSKEY DEMO

  Server           → http://localhost:8080
  WebUI            → http://localhost:8080/ui/
  OIDC discovery   → http://localhost:8080/.well-known/openid-configuration

  Register page    → http://localhost:8080/ui/passkey-register.html

  Password logins:
    alice / alice123  (admins, editors)
    bob   / bob123   (editors)
    carol / carol123

  Passkey login:   no

  RP ID:           localhost
  DB:              /tmp/ahdapa-passkey-demo.db (delete to reset)

  Press Ctrl-C to stop.

Enabling passkey login

Step 1 — start the demo

contrib/demo/passkey/run.sh

Step 2 — register a passkey for alice

Open http://localhost:8080/ui/passkey-register.html in a browser. Enter alice and click Register passkey. The browser prompts for authentication via platform authenticator, a hardware key, or a virtual authenticator in DevTools.

After the ceremony completes, the page displays a line in the form:

passkey:<base64-credentialId>,<base64-COSE_Key>

Copy this line.

Step 3 — create the overlay file

cp contrib/demo/passkey/users.passkeys.toml.example \
   contrib/demo/passkey/users.passkeys.toml

Edit users.passkeys.toml and paste the copied line into alice’s passkeys array. Ensure the password field is also present so password login continues to work:

[[user]]
username    = "alice"
password    = "alice123"
name        = "Alice Admin"
given_name  = "Alice"
family_name = "Admin"
email       = "alice@dev.local"
groups      = ["admins", "editors"]
passkeys    = [
    "passkey:AAAA...base64...,BBBB...base64...",
]

Step 4 — restart the demo

Stop the running server (Ctrl-C), then:

contrib/demo/passkey/run.sh

The startup output now shows Passkey login: yes (alice). On the login page, entering alice triggers the passkey prompt from the browser instead of the password field.

Configuration notes

FileDescription
ahdapa.tomlServer config with passkey_rp_id = "localhost" and GSSAPI disabled
users.tomlBase users file (alice, bob, carol) with password login only
users.passkeys.toml.exampleTemplate for the passkey overlay; copy and fill in credential
users.passkeys.tomlYour local overlay (gitignored); merged with users.toml at startup
passkey-register.htmlRegistration helper page; served from webui/dist/
run.shBuild and launch script

The run.sh script merges the overlay and base files before starting:

# If overlay exists, prepend it (overlay entries take precedence).
cat users.passkeys.toml users.toml > /tmp/ahdapa-passkey-demo-users.toml

The merged file path is set in ahdapa.toml:

[users]
file = "/tmp/ahdapa-passkey-demo-users.toml"

RP ID

The passkey_rp_id must match the origin of the page that registered the credential. For localhost development it is always "localhost". For a production FreeIPA deployment, set it to the IPA domain name (e.g. "ipa.example.com"), which is also what FreeIPA uses when managing passkeys via ipa user-add-passkey.

[ipa]
passkey_rp_id = "localhost"

Resetting

Delete the demo database to discard all CRDT state (OAuth2 clients, keys) and start fresh:

rm /tmp/ahdapa-passkey-demo.db

The passkey credential registered in the browser is separate from the database: it is stored in the operating system’s credential store or on the hardware key. You can re-register any time using the registration page.

See also