Skip to content

Ktor backend sample

A Ktor backend for local and mobile end-to-end passkey flows.

Routes

  • POST /webauthn/registration/start
  • POST /webauthn/registration/finish
  • POST /webauthn/authentication/start
  • POST /webauthn/authentication/finish
  • GET /health
  • GET /.well-known/assetlinks.json
  • GET /.well-known/apple-app-site-association
  • GET /apple-app-site-association
  • GET /webauthn/cli/browser

Run

./gradlew :sample:backend-ktor:run

Environment variables:

  • PORT (default 8080)
  • WEBAUTHN_SAMPLE_ATTESTATION (STRICT default, set NONE to explicitly disable strict attestation verification for local bring-up)
  • ANDROID_PACKAGE_NAME (default dev.webauthn.samples.composepasskey.android)
  • ANDROID_SHA256 (default placeholder; set for real-device app-link verification)
  • IOS_APP_ID (canonical iOS app ID for AASA webcredentials.apps, default placeholder)
  • IOS_TEAM_ID (optional helper input, used to derive IOS_APP_ID when IOS_APP_ID is unset)
  • IOS_BUNDLE_ID (optional helper input, used to derive IOS_APP_ID when IOS_APP_ID is unset)

IOS_APP_ID resolution:

  1. If IOS_APP_ID is set, it is used as-is.
  2. Else if both IOS_TEAM_ID and IOS_BUNDLE_ID are set, backend derives IOS_APP_ID=${IOS_TEAM_ID}.${IOS_BUNDLE_ID}.
  3. Else backend uses placeholder TEAMID.com.example.app and logs a warning.

ngrok helper

For physical-device flows with associated domains:

./sample/backend-ktor/start-server.sh

This helper updates root local.properties with WEBAUTHN_DEMO_ENDPOINT, WEBAUTHN_DEMO_RP_ID, and the iOS/web WEBAUTHN_DEMO_ORIGIN, then starts the backend with matching association values. The Android host derives its android:apk-key-hash:... ceremony origin from the installed app's signing certificate; ANDROID_SHA256 must describe that same certificate for the served Digital Asset Links statement.