Firebase Authentication苹果登录退出重登时重复凭证错误求助
Apple Sign-In + Firebase Auth 退出后重登出现重复凭证错误的解决方法
我开发跨设备数据传输游戏,用Unity集成了Apple Sign-In Asset和Firebase Auth,首次登录正常,但Firebase SignOut后重新调用登录逻辑时,出现Duplicate credential received错误。已尝试每次登录生成新Nonce,但问题依旧。
问题根源
- 重复使用Apple ID Token:从
PlayerPrefs读取的appleIdToken是首次登录时获取的旧Token,Firebase会标记已使用过的凭证,重复提交必然触发重复凭证错误。 - 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
相关产品推荐
相关产品推荐

