Skip to main content
Mera v0.2.0 通过原生 WebAuthn 客户端添加了 React Native 支持。用户可以在 Web 上创建 passkey,在 iOS 或 Android 上使用同步的 passkey 登录,并在每个应用中派生出相同的 Monad 账户。 Web 应用和移动应用必须使用相同的 relying party ID(rpId)。passkey 提供商还必须将 passkey 同步到移动设备并支持 WebAuthn PRF 扩展。
React Native 演示 展示了完整流程,包括 passkey 登录、由生物识别把关的设备存储、账户恢复以及交易签名。

前置条件

  • Node.js 24 或更高版本
  • 已初始化的 Expo 项目,且已安装 expo
  • @category-labs/mera v0.2.0 或更高版本
  • 您自己控制的 HTTPS 主机,用于 relying party ID 和平台关联文件
  • iOS 18 或更高版本,或 Android 9 或更高版本,且 passkey 提供商支持 PRF
  • iOS 使用 Xcode,Android 使用 Android Studio,并在 PATH 中提供带有 keytool 的 JDK
下面的 Expo 示例使用 development build,因为 react-native-passkey 会调用原生平台 API。

安装

从现有 Expo 项目的根目录运行以下命令。如果要创建新项目:
创建项目的命令会安装 expo 并生成本指南中使用的应用入口点。您无需克隆 Mera 演示。 安装 Mera、react-native-passkey 客户端以及其他依赖:

添加 Hermes crypto polyfill

Mera 需要 crypto.getRandomValues,而 Hermes 并未提供。使用 expo-crypto 创建一个 polyfill:
src/polyfills.ts
在使用 Mera 的代码被导入之前,从应用入口点导入该 polyfill:
index.ts

将应用与 passkey 域名关联

为 relying party ID 选择一个主机,例如 accounts.example.com。仅使用主机名,不要包含 https:// 或路径。 要复用 Web 应用创建的 passkey,Web 应用必须使用相同的 rpId 来创建它。每个移动平台还需要一个公开的关联文件,用于授权原生应用为该主机使用凭据。

iOS

https://accounts.example.com/.well-known/apple-app-site-association 提供以下 JSON:
TEAM_ID 替换为您的 Apple team ID,将 com.example.app 替换为应用的 bundle identifier。将关联域名添加到 Expo 配置:
app.config.ts

Android

https://accounts.example.com/.well-known/assetlinks.json 提供以下 JSON:
将 package name 和 fingerprint 替换为 Android 应用对应的值。包含用于签署应用的每个证书的 fingerprint。下一节说明如何打印默认 Expo debug 证书的 fingerprint。

构建原生应用

配置应用后,生成 ios/android/ 项目。Expo Prebuild 会创建这些目录,并将 react-native-passkey 与原生项目链接:
对于 Android development build,打印生成的 debug 证书的 fingerprint,并在 assetlinks.json 中用该结果替换 SHA256_FINGERPRINT
在测试 passkey 之前,使用该 fingerprint 更新并部署 assetlinks.json。两个平台关联文件都必须通过 HTTPS 公开可用,返回 JSON,并且不经过重定向进行响应。 然后编译并运行 development build。iOS:
Android:
Expo Go 无法运行此应用,因为它不包含原生 passkey 模块。

创建或复用 passkey

React Native 不暴露浏览器的 WebAuthn API。将 Mera 的 reactNativeWebAuthnClient 传递给每个运行 passkey ceremony 的函数:
src/passkey.ts
调用 signIn 时不带 credential ID,可以让平台提供该 relying party 可用的任何 passkey。如果在 Web 上创建的 passkey 已同步到设备,选择它将返回相同的 PRF 输出,从而派生出相同的账户。

派生 Monad 账户

从返回的 PRF 输出派生标准 EVM BIP-44 密钥:
src/wallet.ts
派生路径必须与 Web 应用一致。仅当您打算从同一 passkey 使用另一个账户时才递增 index

发送交易

创建一个签名会话,将其适配为 viem 账户,并在 Monad 上发送交易:
src/send-transaction.ts
主网请使用 monad 代替 monadTestnet。使用其他交易类型之前,请参见 Gas 定价

存储和解锁账户

credential ID 是元数据,不包含密钥材料。而 PRF 输出可以派生账户的私钥,必须作为敏感密钥材料对待。 为获得更流畅的移动体验,应用可以将 PRF 输出存储在受生物识别或设备凭据保护的平台安全存储中。这样应用无需在每次交易时都显示 passkey 选择器即可解锁现有账户。
  • 不要将 PRF 输出存储在 AsyncStorage 或应用日志中。
  • 当用户锁定钱包、退出登录或应用会话过期时,结束签名会话。
  • 派生会话后清除临时的 PRF、seed 和私钥缓冲区。
  • 在显示恢复短语或执行其他敏感导出之前,再次请求 passkey。
移动演示存储实现 使用 Expo SecureStore 展示了此模式。

故障排查

  • PRF_UNAVAILABLE:所选的 passkey 提供商或操作系统未返回 PRF 扩展。请检查 Mera 的 Authenticator 支持
  • 首次请求出现 PASSKEY_OPERATION_FAILED:确认关联文件可无重定向访问,并且包含已安装应用的准确 bundle 或 package 标识符及签名证书。
  • 移动端地址与 Web 地址不同:确认两个应用使用相同的 rpId、相同的 passkey 以及相同的 BIP-44 账户索引。

延伸阅读