Expo React Native导入JWT包触发crypto未找到错误,应用崩溃
解决Expo React Native对接App Store API的JWT签名问题
一、修复「ReferenceError: Can't find variable: crypto」错误
Expo React Native环境没有内置Node.js的crypto模块,jose包默认依赖该模块,因此需要用Expo官方提供的加密库替代:
- 安装
expo-crypto(符合Web Crypto标准,适配Expo环境):
npx expo install expo-crypto
- 在代码中配置
jose使用expo-crypto提供的加密实现:
import * as JSW from 'jose'; import * as Crypto from 'expo-crypto'; // 给jose设置自定义crypto环境 JSW.setCrypto(Crypto);
二、修正JWT签名代码逻辑
你当前的SignJWT用法存在错误,正确的签名流程需要注意以下细节:
SignJWT构造函数仅接收payload对象,而非包含header和payload的复合对象- JWT头部需通过
setProtectedHeader方法单独设置 - App Store提供的私钥是PEM格式,需要先解析为
KeyObject才能用于签名 - 签名操作是异步的,需用
async/await处理
修正后的完整代码:
import * as JSW from 'jose'; import * as Crypto from 'expo-crypto'; // 配置jose适配Expo环境 JSW.setCrypto(Crypto); export default class AppStoreAPI { private static _instance: AppStoreAPI; static get I() { if (!this._instance) this._instance = new AppStoreAPI(); return this._instance; } tokenCreation = async () => { const credentials = { privateKey: `-----BEGIN PRIVATE KEY----- 你的App Store私钥完整内容 -----END PRIVATE KEY-----`, // 必须保留PEM格式的首尾标识行 apiKeyId: '你的API Key ID', issuerId: '你的Issuer ID' }; const now = Math.round(Date.now() / 1000); const expiresAt = now + 1999; // 遵循App Store要求,令牌有效期不超过20分钟 // 解析PEM格式的ES256私钥 const privateKey = await JSW.importPKCS8(credentials.privateKey, 'ES256'); // 构建并签名JWT const token = await new JSW.SignJWT({ iss: credentials.issuerId, iat: now, exp: expiresAt, aud: 'appstoreconnect-v1', scope: [ 'GET /v1/apps?filter[platform]=IOS' ] }) .setProtectedHeader({ alg: 'ES256', kid: credentials.apiKeyId, typ: 'JWT' }) .sign(privateKey); return token; } }
关键注意事项
- 私钥必须完整保留PEM格式的首尾行,否则会解析失败
- App Store Connect API强制要求签名算法为
ES256,不可更改 - 令牌有效期最长为20分钟,设置
exp时不要超过当前时间+1200秒
内容的提问来源于stack exchange,提问作者Michael Schmitz
相关产品推荐
相关产品推荐

