Skip to main content

Overview

On mobile, passkeys work differently from browsers. Instead of WebAuthn, the Chipi Expo SDK uses:
  • expo-local-authentication — Face ID, Touch ID, and fingerprint gate
  • expo-secure-store — iOS Keychain / Android Keystore for protected key storage
When you set usePasskey: true, the SDK generates a random encryption key, stores it in the device’s secure enclave, and gates it behind biometric authentication.
Always pair a passkey with a PIN backup. The Chipi Passkeys guide (dual-key architecture) requires every passkey wallet to have a mandatory PIN backup so that biometric deletion, device reset, or OS-level passkey loss does not permanently lock the wallet. Pass the user’s PIN as encryptKey alongside usePasskey: true — the SDK stores two encrypted copies of the private key: one unlocked by the biometric key, one unlocked by the PIN. Passkey-only mode (no encryptKey) is supported but labelled not recommended in the SDK source and should not be used in production.
This is a native mobile implementation. For browser (Next.js / React), see Use Passkeys (React) which uses WebAuthn instead.

Prerequisites

  • Expo SDK 55 or later
  • A physical iOS or Android device with biometrics enrolled (Face ID, Touch ID, or fingerprint)
  • A development build — biometrics are not supported in Expo Go
The iOS Simulator does not support biometric authentication. You must test on a real device or configure the simulator to use device passcode fallback.

Installation

Configuration

Add the expo-local-authentication plugin to your app.json to request Face ID permission on iOS:
If you skip faceIDPermission, Apple will reject your app during review and Face ID will fall back to device passcode on iOS without an explanation to the user.
After updating app.json, rebuild your development client:

Usage

Create a wallet with biometric passkey + PIN backup

Pass usePasskey: true, an externalUserId, and the user’s PIN as encryptKey. The SDK uses the biometric-derived key as the primary encryption key and stores a second copy of the private key encrypted with the PIN as a recovery fallback.

Sign a transaction (retrieve the key with biometrics)

When you need the encryption key later (e.g. to sign a transfer), retrieve it from secure storage — this automatically triggers the Face ID / Touch ID prompt:

Use usePasskey: true directly in transaction hooks

useTransfer, useApprove, and useCallAnyContract now use the Expo native passkey adapter automatically when wrapped with @chipi-stack/chipi-expo’s ChipiProvider. When you pass usePasskey: true to those hooks, also pass externalUserId (usually your auth provider user id), so the SDK can fetch the correct key from secure storage:

Migrate an existing PIN wallet to biometrics

If your users already have a PIN-based wallet, migrate them with one call:
After migration, the old PIN (oldEncryptKey) will no longer decrypt the wallet. Store the updated wallet object returned by migrateWalletToPasskeyAsync immediately.

Full Example

How it Works

Security Notes

  • The encryption key is stored in the device’s secure enclave (iOS Keychain / Android Keystore)
  • requireAuthentication: true means the key cannot be read without biometric approval
  • The key never leaves the device
  • If the user uninstalls the app or re-installs it, the key is lost — ensure your users understand wallet recovery options

Utilities Reference