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

Firebase Authentication苹果登录退出重登时重复凭证错误求助

Apple Sign-In + Firebase Auth 退出后重登出现重复凭证错误的解决方法

我开发跨设备数据传输游戏,用Unity集成了Apple Sign-In Asset和Firebase Auth,首次登录正常,但Firebase SignOut后重新调用登录逻辑时,出现Duplicate credential received错误。已尝试每次登录生成新Nonce,但问题依旧。

问题根源

  1. 重复使用Apple ID Token:从PlayerPrefs读取的appleIdToken是首次登录时获取的旧Token,Firebase会标记已使用过的凭证,重复提交必然触发重复凭证错误。
  2. Nonce不匹配:当前代码在Apple Sign-In成功后才生成新的rawNonce,但Apple生成ID Token时用的是登录发起时的Nonce,后续用新Nonce生成的Credential和Token签名不匹配,同时旧Token本身已失效/被使用,双重问题导致报错。

解决方案

1. 每次登录重新发起Apple Sign-In流程,获取新的ID Token

不能复用旧的Apple ID Token,必须在每次登录时重新调用Apple Sign-In接口,获取最新的Token和对应的授权信息。

2. 严格保证Nonce的一致性

  • 发起Apple Sign-In前生成rawNonce,并临时保存(内存或临时存储)
  • 将该rawNonce传给Apple Sign-In接口,用于生成签名后的ID Token
  • 登录Firebase时,必须使用同一个rawNonce来生成Credential

修正后的代码示例

发起Apple Sign-In的逻辑(新增)
private void InitiateAppleSignIn()
{
    // 生成新的Nonce并临时保存
    var rawNonce = Guid.NewGuid().ToString();
    PlayerPrefs.SetString(AppleRawNonceKey, rawNonce);
    
    // 调用Apple Sign-In插件的登录方法,传入rawNonce
    // 示例(根据你使用的Apple Sign-In Asset调整):
    AppleSignInController.Instance.SignInWithApple(rawNonce, OnAppleSignInCompleted);
}

private void OnAppleSignInCompleted(bool success, string idToken, string error)
{
    if (success)
    {
        // 保存新获取的ID Token
        PlayerPrefs.SetString(AppleUserTokenKey, idToken);
        SignInWithAppleSuccessful();
    }
    else
    {
        Debug.LogError("Apple Sign-In failed: " + error);
    }
}
修正后的SignInWithAppleSuccessful方法
private void SignInWithAppleSuccessful()
{ 
    auth = Firebase.Auth.FirebaseAuth.DefaultInstance;
    
    // 获取本次登录的新Token和对应的Nonce
    var appleIdToken = PlayerPrefs.GetString(AppleUserTokenKey);
    var rawNonce = PlayerPrefs.GetString(AppleRawNonceKey);
    
    // 验证Token和Nonce是否有效
    if (string.IsNullOrEmpty(appleIdToken) || string.IsNullOrEmpty(rawNonce))
    {
        resultText.text = "Invalid Apple credentials";
        return;
    }
    
    var user = auth.CurrentUser;
            
    if (auth.CurrentUser != null) 
    {
        userId.text = user.UserId;
        AuthenticationSuccessful(auth.CurrentUser);
        AddListenersToDatabase();
        // 清除临时存储的凭证,避免重复使用
        PlayerPrefs.DeleteKey(AppleUserTokenKey);
        PlayerPrefs.DeleteKey(AppleRawNonceKey);
    }
    else
    {
        resultText.text = "No current user found";
        Firebase.Auth.Credential credential = Firebase.Auth.OAuthProvider.GetCredential("apple.com", appleIdToken, rawNonce, null);

        auth.SignInAndRetrieveDataWithCredentialAsync(credential)
        .ContinueWith(task => {
            if (task.IsCanceled) 
            {
                Debug.LogError("BB 1 SignInAndRetrieveDataWithCredentialAsync was canceled.");
                return;
            }
            if (task.IsFaulted) {
                Debug.LogError("BB 2 SignInAndRetrieveDataWithCredentialAsync encountered an error: " + task.Exception);
                // 登录失败后清除无效凭证
                PlayerPrefs.DeleteKey(AppleUserTokenKey);
                PlayerPrefs.DeleteKey(AppleRawNonceKey);
                return;
            }
        
            Firebase.Auth.SignInResult result = task.Result;
            resultText.text = "User signed in successfully : " + result.User.UserId;
            userId.text = result.User.UserId;
            
            AuthenticationSuccessful(result.User);
            AddListenersToDatabase();
            // 清除临时存储的凭证
            PlayerPrefs.DeleteKey(AppleUserTokenKey);
            PlayerPrefs.DeleteKey(AppleRawNonceKey);
        });
    }
}
退出方法(优化后)
if (auth.CurrentUser != null)
{
    auth.SignOut();
    RemoveListenerFromDatabase();         
    resultText.text = "User signed out";
    // 退出时清除可能残留的凭证
    PlayerPrefs.DeleteKey(AppleUserTokenKey);
    PlayerPrefs.DeleteKey(AppleRawNonceKey);
}

额外注意事项

  • Apple ID Token有有效期(通常10分钟),即使不退出,过期后也需要重新发起登录流程获取新Token
  • 不要长期存储Apple ID Token在本地,仅在登录流程中临时保存,成功后立即清除
  • 确保Apple Sign-In插件的配置正确,特别是Nonce的传递逻辑符合Apple的要求

内容的提问来源于stack exchange,提问作者Berk

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 10:27:45