Skip to content

iOS host sample

A ready-to-run iOS host app for the shared sample:compose-passkey Compose UI.

Use this sample when you want to run the passkey demo on a connected iPhone from Xcode with minimal setup.

What is included

  • A committed Xcode app project (ComposePasskeyIos.xcodeproj).
  • SwiftUI app shell that mounts Kotlin MainViewController() from sample:compose-passkey.
  • Build phase script that runs :sample:compose-passkey:embedAndSignAppleFrameworkForXcode.

Quick run on a device with a free Apple account

This path verifies the app is runnable on a real phone without a paid Apple Developer Program membership.

  1. Open Xcode project:
open sample/compose-passkey-ios/ComposePasskeyIos.xcodeproj
  1. In Xcode target settings (ComposePasskeyIos):
  2. Set a unique bundle ID (for example dev.webauthn.samples.composepasskey.ios.<yourname>).
  3. Set Signing & Capabilities to your personal team.
  4. Keep automatic signing enabled.

  5. Select your connected iPhone and run.

Expected result: - App installs and launches. - Compose UI renders with the Auth screen first (Register / Sign In). - Signed-in debug logs remain hidden unless the title is double-tapped.

Note: - Passkey registration and sign-in may fail with a free account when the Associated Domains entitlement or domain association is unavailable.

Complete passkey path with Associated Domains

Use this path when your signing setup supports Associated Domains and you want successful registration and sign-in.

  1. Start backend with tunnel helper:
IOS_TEAM_ID=<TEAM_ID> \
IOS_BUNDLE_ID=<BUNDLE_ID> \
./sample/backend-ktor/start-server.sh
  1. Ensure app identity matches backend AASA config:
  2. Canonical value is IOS_APP_ID.
  3. If IOS_APP_ID is unset, backend derives it from IOS_TEAM_ID.IOS_BUNDLE_ID.
  4. IOS_APP_ID must match your signed app ID (<TEAM_ID>.<BUNDLE_ID>).

  5. In Xcode, add capability:

  6. Signing & Capabilities -> Associated Domains
  7. Add webcredentials:<your-https-domain> (the ngrok host from helper output).

  8. Rebuild and run the iOS app.

Expected result: - Register completes. - Sign In completes. - Signed-in extension demo screen is shown after successful sign-in. - PasskeyDemo logs appear in Xcode console and in the hidden in-app debug sheet (title double-tap).

Environment variables used by the shared sample

Build-time values come from Gradle properties / env vars / local.properties:

  • WEBAUTHN_DEMO_ENDPOINT
  • WEBAUTHN_DEMO_RP_ID
  • WEBAUTHN_DEMO_ORIGIN
  • WEBAUTHN_DEMO_USER_ID
  • WEBAUTHN_DEMO_USER_NAME

Backend iOS association identity:

  • IOS_APP_ID (canonical)
  • IOS_TEAM_ID (optional helper input)
  • IOS_BUNDLE_ID (optional helper input)

Troubleshooting

  • Signing error about provisioning or the profile:
  • Re-select your personal or team signing identity and unique bundle ID.
  • Build phase cannot find Gradle task:
  • Run from repo root and ensure sample:compose-passkey iOS framework targets are configured.
  • Registration or sign-in fails with domain or association errors:
  • Check IOS_APP_ID alignment and webcredentials:<domain> entry.
  • Verify backend serves /.well-known/apple-app-site-association for the exact HTTPS domain.
  • Simulator works but device passkey flow fails:
  • This is usually signing/entitlement/domain mismatch rather than Compose wiring.

Maintaining this project

If project.yml changes, regenerate the Xcode project:

xcodegen generate --spec sample/compose-passkey-ios/project.yml