README.md

Device verification and passkeys

ts
1import * as device from '@solid-native/auth/device';
2import * as passkeys from '@solid-native/auth/passkeys';
3
4const capabilities = await device.capabilities();
5const verified = await device.verify({ reason: 'Confirm this action', policy: 'device' });
6
7const credential = await passkeys.create(registrationOptionsFromYourServer);
8if (credential) await sendRegistrationToYourServer(credential);
9const assertion = await passkeys.get(authenticationOptionsFromYourServer);
10if (assertion) await sendAssertionToYourServer(assertion);

Local device.verify is not server sign-in and does not unlock secure storage. biometric requires a supported strong biometric; device permits the system's device-credential fallback. It returns false for cancellation and rejects unavailability/lockout. Capability checks do not prompt or guarantee that the next verification succeeds. biometricEnrolled is null when the OS cannot determine it.

Passkeys use AuthenticationServices on iOS and Credential Manager on Android. Options and responses use WebAuthn JSON with canonical, unpadded base64url byte fields, not ArrayBuffers. The supported subset includes ES256 credentials, user-verification preferences, allow/exclude credential IDs, and none/direct attestation. Unknown/unsupported options reject instead of being silently dropped: timeout, transports, resident-key overrides, extensions, and conditional mediation are not in the initial cross-platform contract. iOS passkeys require iOS 16+; nonempty registration exclusions require iOS 17.4+. User cancellation returns null. Provider errors reject.

Your server must generate one-time challenges and verify all responses, including RP ID, allowed native/web origins, challenge, user verification, signature, and credential ownership. Sending back the provider's JSON is not itself authentication. No private key is returned. iCloud Keychain can be the provider, but the OS/user chooses providers; the API does not promise a particular provider or synchronization.

Production setup is app-specific:

  • iOS: signed Associated Domains entitlement webcredentials:your-domain, matching apple-app-site-association on that domain, and Face ID usage description.
  • Android: matching signed package/certificate entries and credential-sharing relation in the domain's Digital Asset Links, installed Credential Manager provider, biometric permission, and a foreground FragmentActivity.

The sample host compiles/registers the modules but has no claimed relying-party domain or production signing. End-to-end creation/sign-in and iCloud sync are therefore not established by local tests. A third-party GitHub client cannot create native passkeys for github.com without GitHub's domain authorization; use its documented OAuth flow through @solid-native/web instead.