Expo托管式集成Firebase遇Apple登录错误:auth/invalid-credential
Expo托管式工作流集成Firebase Apple登录报错解决
问题描述
在Expo托管式工作流中集成Firebase实现Apple登录时,遇到以下错误:
Error: [auth/invalid-credential] The supplied auth credential is malformed or has expired.
现有代码
导入部分
import auth from '@react-native-firebase/auth' import { AppleButton, appleAuth } from '@invertase/react-native-apple-authentication';
登录函数与组件
async function onAppleButtonPress() { const appleAuthRequestResponse = await appleAuth.performRequest({ requestedOperation: appleAuth.Operation.LOGIN, requestedScopes: [appleAuth.Scope.FULL_NAME, appleAuth.Scope.EMAIL], }) const { identityToken, nonce } = appleAuthRequestResponse; console.log(identityToken); console.log(nonce); const appleCredential = auth.AppleAuthProvider.credential(identityToken, nonce) console.log(appleCredential); return auth().signInWithCredential(appleCredential); } {isAppleLoginAvailable && <AppleButton buttonStyle={AppleButton.Style.BLACK} buttonType={AppleButton.Type.SIGN_IN} style={{ width: 250, height: 45, }} onPress={() => onAppleButtonPress().then(() => console.log('Apple sign-in complete!')).catch((e) => console.log(e))} />}
解决方案
1. 修正Nonce的生成与使用逻辑
Firebase要求Apple登录的nonce必须是开发者自行生成的随机字符串,而非Apple返回的nonce。Apple会将你传入的nonce加密后返回,用来验证请求合法性。修改步骤:
- 先添加随机nonce生成函数(需安装
expo-crypto):import * as Crypto from 'expo-crypto'; const generateNonce = () => { const randomBytes = Crypto.getRandomBytes(16); return Crypto.bytesToBase64(randomBytes) .replace(/\+/g, '-') .replace(/\//g, '_') .replace(/=+$/, ''); }; - 在发起Apple登录请求时传入自定义nonce:
async function onAppleButtonPress() { const nonce = generateNonce(); // 生成自定义nonce const appleAuthRequestResponse = await appleAuth.performRequest({ requestedOperation: appleAuth.Operation.LOGIN, requestedScopes: [appleAuth.Scope.FULL_NAME, appleAuth.Scope.EMAIL], nonce: nonce, // 传入自定义nonce }) const { identityToken } = appleAuthRequestResponse; // 使用自己生成的nonce创建Firebase凭证,而非Apple返回的 const appleCredential = auth.AppleAuthProvider.credential(identityToken, nonce) return auth().signInWithCredential(appleCredential); }
2. 验证Identity Token有效性
- 打印
identityToken,确认其为以eyJ开头的有效JWT字符串。若为空或格式错误:- 检查Apple开发者后台是否已启用「Sign in with Apple」,且App ID的配置正确。
- 确认Expo项目
app.json中已配置ios.bundleIdentifier,并添加"ios": { "usesAppleSignIn": true }。
3. 检查Firebase配置
- 确认Firebase控制台中已启用Apple登录方式,且正确上传了Apple服务ID和私钥。
- 确保Firebase的
GoogleService-Info.plist已正确配置到Expo项目(托管式工作流可通过expo-firebase-app自动同步,需确认凭证无误)。
4. 更换为Expo官方Apple认证库(推荐)
@invertase/react-native-apple-authentication在Expo托管式工作流中可能存在兼容性问题,建议使用Expo官方的expo-apple-authentication:
- 安装依赖:
npx expo install expo-apple-authentication - 替换导入与代码:
import auth from '@react-native-firebase/auth'; import * as AppleAuthentication from 'expo-apple-authentication'; import * as Crypto from 'expo-crypto'; const generateNonce = () => { const randomBytes = Crypto.getRandomBytes(16); return Crypto.bytesToBase64(randomBytes) .replace(/\+/g, '-') .replace(/\//g, '_') .replace(/=+$/, ''); }; async function onAppleButtonPress() { const nonce = generateNonce(); const credential = await AppleAuthentication.signInAsync({ requestedScopes: [ AppleAuthentication.AppleAuthenticationScope.FULL_NAME, AppleAuthentication.AppleAuthenticationScope.EMAIL, ], nonce: nonce, }); const appleCredential = auth.AppleAuthProvider.credential(credential.identityToken, nonce); return auth().signInWithCredential(appleCredential); }
内容的提问来源于stack exchange,提问作者Patryk Opiela
相关产品推荐
相关产品推荐

