rpId). The passkey provider must also sync the passkey to the mobile device and support the WebAuthn PRF extension.
The React Native demo shows the complete flow, including passkey sign-in, biometric-gated device storage, account recovery, and transaction signing.
Requirements
- Node.js 24 or later
- An initialized Expo project with
expoinstalled @category-labs/merav0.2.0 or later- An HTTPS host that you control for the relying party ID and platform association files
- iOS 18 or later, or Android 9 or later with a passkey provider that supports PRF
- Xcode for iOS, or Android Studio and a JDK with
keytoolon yourPATHfor Android
react-native-passkey calls native platform APIs.
Install
Run the following commands from the root of an existing Expo project. To create a new project instead:expo and creates the app entry point used in this guide. You do not need to clone the Mera demo.
Install Mera, the react-native-passkey client, and the other dependencies:
Add the Hermes crypto polyfill
Mera needscrypto.getRandomValues, which Hermes does not provide. Create a polyfill using expo-crypto:
src/polyfills.ts
index.ts
Link the app to the passkey domain
Choose a host such asaccounts.example.com for the relying party ID. Use only the host name, without https:// or a path.
To reuse a passkey created by a web app, the web app must create it with this same rpId. Each mobile platform also requires a public association file that authorizes the native app to use credentials for the host.
iOS
Serve the following JSON fromhttps://accounts.example.com/.well-known/apple-app-site-association:
TEAM_ID with your Apple team ID and com.example.app with the app’s bundle identifier. Add the associated domain to the Expo configuration:
app.config.ts
Android
Serve the following JSON fromhttps://accounts.example.com/.well-known/assetlinks.json:
Build the native app
Generate theios/ and android/ projects after configuring the app. Expo Prebuild creates these directories and links react-native-passkey with the native projects:
SHA256_FINGERPRINT in assetlinks.json with the result:
assetlinks.json with this fingerprint before testing passkeys. Both platform association files must be publicly available over HTTPS, return JSON, and respond without a redirect.
Then compile and run the development build. For iOS:
Create or reuse a passkey
React Native does not expose the browser WebAuthn APIs. Pass Mera’sreactNativeWebAuthnClient to every function that runs a passkey ceremony:
src/passkey.ts
signIn without a credential ID lets the platform offer any passkey available for the relying party. If the passkey created on the web has synced to the device, selecting it returns the same PRF output and therefore derives the same account.
Derive a Monad account
Derive the standard EVM BIP-44 key from the returned PRF output:src/wallet.ts
index only when you intend to use another account from the same passkey.
Send a transaction
Create a signing session, adapt it to a viem account, and send a transaction on Monad:src/send-transaction.ts
monad instead of monadTestnet for mainnet. See Gas pricing before using other transaction types.
Store and unlock the account
The credential ID is metadata and does not contain key material. The PRF output, however, can derive the account’s private keys and must be treated as secret key material. For a smoother mobile experience, an app can store the PRF output in platform secure storage protected by biometrics or the device credential. This lets the app unlock an existing account without showing the passkey picker for every transaction.- Do not store the PRF output in
AsyncStorageor application logs. - End the signing session when the user locks the wallet, signs out, or the app’s session expires.
- Clear temporary PRF, seed, and private-key buffers after deriving the session.
- Request the passkey again before displaying a recovery phrase or performing another sensitive export.
Troubleshooting
PRF_UNAVAILABLE: The selected passkey provider or operating system did not return the PRF extension. Check Mera’s authenticator support.PASSKEY_OPERATION_FAILEDon the first request: Confirm that the association file is reachable without a redirect and contains the installed app’s exact bundle or package identifier and signing certificate.- The mobile address differs from the web address: Confirm that both apps use the same
rpId, the same passkey, and the same BIP-44 account index.

