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

Unity中Apple Sign In对接Firebase Auth时ID Token解析失败求助

Unity中Apple Sign In对接Firebase Auth时ID Token解析失败问题

问题描述

对接过程中出现以下错误:

Failed to sign in with Firebase using Apple credentials: One or more errors occurred. (Unable to parse the ID Token.)

开发环境:macOS平台,Unity,Firebase SDK版本11.2,已声明public FirebaseAuth auth和public FirebaseUser User对象。

登录实现代码

private void SignInWithApple()
{
    var rawNonce = GenerateRandomString(32);
    nonce1 = GenerateSHA256NonceFromRawNonce(rawNonce);

    var loginArgs = new AppleAuthLoginArgs(LoginOptions.IncludeEmail | LoginOptions.IncludeFullName , nonce1 );
    Debug.Log("Apple login is being initiated.");

    this._appleAuthManager.LoginWithAppleId(
        loginArgs,
        async credential =>
        {   
            Debug.Log("Credential is being obtained.");
            if (credential is IAppleIDCredential appleIdCredential)
            {
                var authorizationCode = Encoding.UTF8.GetString(appleIdCredential.AuthorizationCode);
                PlayerPrefs.SetString(AppleUserIdKey, appleIdCredential.User);

                var identityToken = System.Convert.ToBase64String(appleIdCredential.IdentityToken);

                Debug.Log($"Apple login information is being transferred to Firebase credential. identityToken: {identityToken}");

                var appleCredential = OAuthProvider.GetCredential("apple.com", identityToken, nonce1, null);
                
                Debug.Log($"Apple login information has been transferred to Firebase credential. {appleCredential}");
                try
                {
                    var firebaseUser = await auth.SignInWithCredentialAsync(appleCredential);
                    AddStatusText($"Firebase user info: Email = {firebaseUser.Email}, Id = {firebaseUser.UserId}, Name = {firebaseUser.DisplayName}");
                    Debug.Log("Firebase user info: Email = " + firebaseUser.Email + ", Id = " + firebaseUser.UserId + ", Name = " + firebaseUser.DisplayName);
                    Debug.Log($"Apple login information has been transferred to Firebase credential.");
                    StartCoroutine(InitializeNewUserData(firebaseUser.Email, firebaseUser.DisplayName, "AppleLogin"));
                    StartCoroutine(InitializeFirebaseCoroutine());
                }
                catch (Exception e)
                {
                    Debug.LogError("Failed to sign in with Firebase using Apple credentials: " + e.Message);
                }
            }
        },
        error =>
        {
            var authorizationErrorCode = error.GetAuthorizationErrorCode();
            Debug.LogWarning("Sign in with Apple failed. Error: " + authorizationErrorCode.ToString() + " " + error.ToString());
        });
}

Nonce生成代码

public static string GenerateRandomString(int length)
{
    if (length <= 0)
    {
        throw new Exception("Expected nonce to have positive length");
    }

    const string charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._";
    var cryptographicallySecureRandomNumberGenerator = new RNGCryptoServiceProvider();
    var result = string.Empty;
    var remainingLength = length;

    var randomNumberHolder = new byte[1];
    while (remainingLength > 0)
    {
        var randomNumbers = new List<int>(16);
        for (var randomNumberCount = 0; randomNumberCount < 16; randomNumberCount++)
        {
            cryptographicallySecureRandomNumberGenerator.GetBytes(randomNumberHolder);
            randomNumbers.Add(randomNumberHolder[0]);
        }

        for (var randomNumberIndex = 0; randomNumberIndex < randomNumbers.Count; randomNumberIndex++)
        {
            if (remainingLength == 0)
            {
                break;
            }

            var randomNumber = randomNumbers[randomNumberIndex];
            if (randomNumber < charset.Length)
            {
                result += charset[randomNumber];
                remainingLength--;
            }
        }
    }

    return result;
}

private static string GenerateSHA256NonceFromRawNonce(string rawNonce)
{
    var sha = new SHA256Managed();
    var utf8RawNonce = Encoding.UTF8.GetBytes(rawNonce);
    var hash = sha.ComputeHash(utf8RawNonce);

    var result = string.Empty;
    for (var i = 0; i < hash.Length; i++)
    {
        result += hash[i].ToString("x2");
    }

    return result;
}

Xcode错误日志

<<SignInWithApple>b__49_0>d:MoveNext()
System.Runtime.CompilerServices.AsyncVoidMethodBuilder:Start(TStateMachine&)
FirebaseModules:<SignInWithApple>b__49_0(ICredential)
AppleAuth.CallbackHandler:ExecutePendingCallbacks()

 Firebase.Auth.Credential
<<SignInWithApple>b__49_0>d:MoveNext()
System.Runtime.CompilerServices.AsyncVoidMethodBuilder:Start(TStateMachine&)
FirebaseModules:<SignInWithApple>b__49_0(ICredential)
AppleAuth.CallbackHandler:ExecutePendingCallbacks()

Failed to sign in with Firebase using Apple credentials: One or more errors occurred. (Unable to parse the ID Token.)
<<SignInWithApple>b__49_0>d:MoveNext()
System.Threading.ExecutionContext:RunInternal(ExecutionContext, ContextCallback, Object, Boolean)
System.Runtime.CompilerServices.MoveNextRunner:Run()
UnityEngine.WorkRequest:Invoke()
UnityEngine.UnitySynchronizationContext:Exec()

修复方案

1. 修正ID Token的获取方式

Apple返回的IdentityToken已经是URL安全的Base64编码字符串,无需二次编码。修改代码中获取identityToken的行:

// 替换原代码行
var identityToken = System.Text.Encoding.UTF8.GetString(appleIdCredential.IdentityToken);

2. 验证Nonce处理逻辑

  • 确认GenerateSHA256NonceFromRawNonce方法生成的是小写十六进制字符串(已符合要求)
  • 确保传递给Apple的nonce是原始随机字符串的SHA256哈希,而非原始字符串

3. 检查Firebase与Apple开发者后台配置

  • Firebase控制台中开启Apple登录提供商,配置正确的Team ID、服务ID和签名证书
  • Apple开发者后台中,对应服务ID已启用Sign In with Apple,回调URL与Firebase配置一致

4. 验证ID Token格式

使用JWT解析工具检查获取到的identityToken是否为有效的JWT格式,确认包含iss(应为https://appleid.apple.com)、sub等必要字段,且签名有效。

5. 确保异步回调在主线程执行

Unity中Firebase的异步回调可能在后台线程触发,使用UnityMainThreadDispatcher或手动切换到主线程处理登录后的逻辑,避免线程问题导致的解析错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 03:10:01