You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 16:00:39