firebase - 将两个以上的帐户合并为一个
问题描述
我有一个很奇怪或有点可以理解的(?)问题。
我的 firebase 项目支持 4 种类型的身份验证:Google、Apple、Facebook 和匿名。
我创建了 2 个帐户。一个有谷歌与facebook链接,另一个只有苹果。然后我在苹果账户上链接已经与谷歌链接的同一个 Facebook 账户。
Firebase 控制台显示没有变化,但每次我登录苹果帐户时,firebase 都会返回谷歌的 UID。
我有点明白所有都链接到一个帐户,但我不明白为什么苹果的 UID 没有被删除,谷歌的 UID 没有来自 firebase 控制台的苹果提供商。
另一种情况:分别创建 3 个帐户:Google、Apple 和 Facebook。将所有内容链接在一起。每次我登录时,firebase 都会返回 facebook 的 UID。(这是我完全无法理解的原因。)
如果正常,如果我想在firebase控制台上将其视为一个帐户,我应该在控制台或我的项目上手动管理它们吗?
编辑: 火力控制台
Unity FirebaseAuth.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Firebase.Auth;
using System.Text;
using System.Security.Cryptography;
using UnityEngine.SocialPlatforms;
#if !UNITY_IOS
using GooglePlayGames;
using GooglePlayGames.BasicApi;
using GooglePlayGames.OurUtils;
#else
using AppleAuth;
using AppleAuth.Native;
using AppleAuth.Enums;
using AppleAuth.Extensions;
using AppleAuth.Interfaces;
#endif
public class FirebaseAuth : MonoBehaviour
{
public enum eMOBILEPLATFORM_STATUS
{
CONNECTED,
DISCONNECT,
ERROR,
LOGIN_WAIT,
};
private static FirebaseAuth _instance;
protected eMOBILEPLATFORM_STATUS _accountStatus = eMOBILEPLATFORM_STATUS.DISCONNECT;
#if UNITY_IOS
private IAppleAuthManager _appleAuthManager;
#endif
public eMOBILEPLATFORM_STATUS Status { get { return _accountStatus; } }
public FirebaseAuth auth;
private string _accessToken = string.Empty;
public static FirebaseAuth Instance
{
get
{
if (_instance == null)
{
_instance = FindObjectOfType(typeof(FirebaseAuth)) as FirebaseAuth;
if (_instance == null)
{
Debug.LogError("Missing GlobalObject, Use for Firebase");
return null;
}
}
return _instance;
}
}
void Update()
{
#if UNITY_IOS
if (_appleAuthManager != null) _appleAuthManager.Update();
#endif
}
public void Init()
{
#if !UNITY_IOS
PlayGamesClientConfiguration config = new PlayGamesClientConfiguration
.Builder()
.RequestServerAuthCode(false)
.RequestIdToken()
.Build();
PlayGamesPlatform.InitializeInstance(config);
PlayGamesPlatform.DebugLogEnabled = true;
PlayGamesPlatform.Activate();
#else
if (AppleAuthManager.IsCurrentPlatformSupported)
{
var deserializer = new PayloadDeserializer();
_appleAuthManager = new AppleAuthManager(deserializer);
}
#endif
Debug.Log("Firebase Init");
auth = FirebaseAuth.DefaultInstance;
_accessToken = string.Empty;
}
#if !UNITY_IOS
public void TryGoogleLogin(bool newLogin = true)
{
if (!Social.localUser.authenticated)
{
Social.localUser.Authenticate(success =>
{
if (success)
{
Debug.Log("login success. " + Social.localUser.userName);
if (newLogin)
{
StartCoroutine(TryGoogleFirebaseLogin(newLogin));
}
else
{
LinkGoogleFirebase();
}
}
else
{
Debug.Log("login failed");
}
});
}
else
{
if (newLogin)
{
StartCoroutine(TryGoogleFirebaseLogin(newLogin));
}
else
{
LinkGoogleFirebase();
}
}
}
public void TryGoogleLogout()
{
if (Social.localUser.authenticated)
{
PlayGamesPlatform.Instance.SignOut();
TryFirebaseLogout();
Debug.Log("logout - done");
}
}
public IEnumerator TryGoogleFirebaseLogin(bool newLogin = true)
{
if (newLogin)
{
auth.Dispose();
auth = FirebaseAuth.DefaultInstance;
}
while (string.IsNullOrEmpty(((PlayGamesLocalUser)Social.localUser).GetIdToken()))
yield return null;
string idToken = ((PlayGamesLocalUser)Social.localUser).GetIdToken();
_accessToken = idToken;
Credential credential = GoogleAuthProvider.GetCredential(idToken, null);
auth.SignInWithCredentialAsync(credential).ContinueWith(task =>
{
if (task.IsCanceled)
{
Debug.LogError("google-CredentialAsync was canceled.");
return;
}
if (task.IsFaulted)
{
Debug.LogError("google-CredentialAsync encountered and error: " + task.Exception);
return;
}
Debug.Log("google login success! :D " + auth.CurrentUser.UserId);
_accountStatus = eMOBILEPLATFORM_STATUS.CONNECTED;
UserConfig.Instance.SaveMobilePlatformLogin(true);
PlayerInfo.Instance.m_bGlobalMobilePlatformLogin = true;
if (DoesProvierExist("facebook.com"))
{
PlayerInfo.Instance.m_bGlobalGuestLogin = false;
UserConfig.Instance.SaveFacebookLogin(true);
FacebookManager.Instance.ChangeFacebookStatus(FacebookManager.eFACEBOOK_STATUS.CONNECTED);
}
});
}
public void LinkGoogleFirebase()
{
if (auth != null)
{
string idToken = ((PlayGamesLocalUser)Social.localUser).GetIdToken();
Credential credential = GoogleAuthProvider.GetCredential(idToken, null);
auth.CurrentUser.LinkWithCredentialAsync(credential).ContinueWith(task =>
{
if (task.IsCanceled)
{
Debug.LogError("google-LinkWithCredentialAsync was canceled.");
return;
}
if (task.IsFaulted)
{
Debug.LogError("google-LinkWithCredentialAsync encountered an error: " + task.Exception);
return;
}
FirebaseUser newUser = task.Result;
Debug.Log("google-Credentials successfully linked to Firebase user: " + newUser.DisplayName + "(" + newUser.UserId + ")");
_accountStatus = eMOBILEPLATFORM_STATUS.CONNECTED;
});
}
}
#endif
public IEnumerator TryFacebookFirebaseLogin(Facebook.Unity.AccessToken accessToken, bool newLogin = false)
{
if (newLogin)
{
auth = FirebaseAuth.DefaultInstance;
}
while (System.String.IsNullOrEmpty(accessToken.TokenString))
yield return null;
_accessToken = accessToken.TokenString;
auth = FirebaseAuth.DefaultInstance;
Credential credential = FacebookAuthProvider.GetCredential(accessToken.TokenString);
auth.SignInWithCredentialAsync(credential).ContinueWith(task =>
{
if (task.IsCanceled)
{
Debug.LogError("facebook-CredentialAsync was canceled.");
return;
}
if (task.IsFaulted)
{
Debug.LogError("facebook-CredentialAsync encountered and error: " + task.Exception);
return;
}
Debug.Log("facebook firebase success! :D " + auth.CurrentUser.UserId);
#if !UNITY_IOS
if(DoesProvierExist("google.com"))
#else
if(DoesProvierExist("apple.com"))
#endif
{
_accountStatus = eMOBILEPLATFORM_STATUS.CONNECTED;
}
});
}
public void LinkFacebookFirebase(Facebook.Unity.AccessToken accessToken)
{
if (auth != null)
{
Credential credential = FacebookAuthProvider.GetCredential(accessToken.TokenString);
auth.CurrentUser.LinkWithCredentialAsync(credential).ContinueWith(task =>
{
if (task.IsCanceled)
{
Debug.LogError("facebook-LinkWithCredentialAsync was canceled.");
return;
}
if (task.IsFaulted)
{
Debug.LogError("facebook-LinkWithCredentialAsync encountered an error: " + task.Exception);
return;
}
FirebaseUser newUser = task.Result;
Debug.Log("facebook-Credentials successfully linked to Firebase user: " + newUser.DisplayName + "(" + newUser.UserId + ")");
FacebookManager.Instance.ChangeFacebookStatus(FacebookManager.eFACEBOOK_STATUS.CONNECTED);
});
}
}
#if UNITY_IOS
public IEnumerator TryAppleFirebaseLogin(bool newLogin = true)
{
if (newLogin)
{
auth.Dispose();
auth = FirebaseAuth.DefaultInstance;
}
string rawNonce = GenerateRandomString(32);
string nonce = GenerateSHA256NonceFromRawNonce(rawNonce);
var loginArgs = new AppleAuthLoginArgs(LoginOptions.IncludeEmail | LoginOptions.IncludeFullName, nonce);
while (auth==null)
yield return null;
_appleAuthManager.LoginWithAppleId(
loginArgs,
credential =>
{
var appleIdCredential = credential as IAppleIDCredential;
var identityToken = Encoding.UTF8.GetString(appleIdCredential.IdentityToken);
var authorizationCode = Encoding.UTF8.GetString(appleIdCredential.AuthorizationCode);
var firebaseCredential = OAuthProvider.GetCredential("apple.com", identityToken, rawNonce, authorizationCode);
auth.SignInWithCredentialAsync(firebaseCredential);
if (appleIdCredential.FullName != null)
{
var userName = appleIdCredential.FullName.ToLocalizedString();
var profile = new UserProfile();
profile.DisplayName = userName;
auth.CurrentUser.UpdateUserProfileAsync(profile);
}
_accessToken = authorizationCode.ToString();
Debug.Log("apple firebase success! :D " + auth.CurrentUser.UserId);
_accountStatus = eMOBILEPLATFORM_STATUS.CONNECTED;
UserConfig.Instance.SaveMobilePlatformLogin(true);
PlayerInfo.Instance.m_bGlobalMobilePlatformLogin = true;
if (DoesProvierExist("facebook.com"))
{
PlayerInfo.Instance.m_bGlobalGuestLogin = false;
UserConfig.Instance.SaveFacebookLogin(true);
}
},
error =>
{
var authorizationErrorCode = error.GetAuthorizationErrorCode();
switch (authorizationErrorCode)
{
case AuthorizationErrorCode.Canceled:
break;
case AuthorizationErrorCode.Unknown:
case AuthorizationErrorCode.InvalidResponse:
case AuthorizationErrorCode.NotHandled:
case AuthorizationErrorCode.Failed:
Debug.LogError("apple-login failed :/ error code: " + authorizationErrorCode);
break;
}
return;
});
}
#endif
public IEnumerator TryGuestFirebaseLogin(bool newLogin = false)
{
if (newLogin)
{
auth.Dispose();
auth = FirebaseAuth.DefaultInstance;
}
while (auth == null)
yield return null;
auth.SignInAnonymouslyAsync().ContinueWith(task =>
{
if (task.IsCanceled)
{
Debug.LogError("guest-SignInAnonymouslyAsync was canceled.");
return;
}
if (task.IsFaulted)
{
Debug.LogError("guest-SignInAnonymouslyAsync encountered an error: " + task.Exception);
return;
}
Firebase.Auth.FirebaseUser newUser = task.Result;
Debug.Log("guest-User signed in successfully :D " + newUser.DisplayName + " (" + newUser.UserId + ")");
});
}
public void UnlinkFirebase(string providerID)
{
if (auth != null && DoesProvierExist(providerID))
{
auth.CurrentUser.UnlinkAsync(providerID).ContinueWith(task =>
{
if (task.IsCanceled)
{
Debug.LogError(providerID + "-UnlinkAsync was canceled.");
return;
}
if (task.IsFaulted)
{
Debug.LogError(providerID + "-UnlinkAsync encountered an error: " + task.Exception);
return;
}
// The user has been unlinked from the provider.
FirebaseUser newUser = task.Result;
Debug.LogFormat(providerID + " Credentials successfully unlinked from user: {0} ({1})", newUser.DisplayName, newUser.UserId);
#if !UNITY_IOS
if (providerID == "google.com")
#else
if (providerID == "apple.com")
#endif
{
_accountStatus = eMOBILEPLATFORM_STATUS.DISCONNECT;
}
});
}
}
public void TryFirebaseLogout()
{
auth.SignOut();
}
private string GenerateRandomString(int 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 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;
}
public string GetAccessToken()
{
return _accessToken;
}
/// <summary>
/// Check the current user has certain provierID.
/// </summary>
/// <param name="providerID"> Such as "facebook.com", "apple.com", "google.com"</param>
/// <returns>false if auth or user is null</returns>
public bool DoesProvierExist(string providerID)
{
FirebaseUser user = auth.CurrentUser;
bool result = false;
int checkCount = 0;
List<string> providers = new List<string>();
if (user != null)
{
foreach (var profile in user.ProviderData)
{
checkCount++;
providers.Add(profile.ProviderId);
if (profile.ProviderId == providerID)
result = true;
}
}
#if _USE_DEBUG_LOG_
string temp = string.Empty;
for (int i = 0; i < providers.Count; i++)
{
temp += providers[i];
if (i != providers.Count - 1)
temp += ", ";
}
Debug.Log("Just in case if you wanna know. There are " + checkCount + " providerID at this account\n"+temp);
#endif
return result;
}
}
这是iphone的xcode日志。
ClickButton (GlobalStart)(04/16/2021 10:22:56)
UIEventButtonClick:OnClick()
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)
LoginFacebook()False
FacebookManager:LoginFacebook()
UIL_Login:Event_Click(String)
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)
2021-04-16 10:22:56.640715+0900 firebaseProject[1006:67274] -canOpenURL: failed for URL: "fbauth2:/" - error: "The operation couldn’t be completed. (OSStatus error -10814.)"
-> applicationWillResignActive()
-> applicationDidBecomeActive()
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)
2021-04-16 10:22:58.701301+0900 firebaseProject[1006:68330] [tcp] tcp_input [C19.1:3] flags=[R] seq=3046356287, ack=0, win=0 state=CLOSED rcv_nxt=3046356287, snd_una=716434727
2021-04-16 10:22:58.705125+0900 firebaseProject[1006:68330] [tcp] tcp_input [C19.1:3] flags=[R] seq=3046356287, ack=0, win=0 state=CLOSED rcv_nxt=3046356287, snd_una=716434727
CONNECTTING() True
FacebookManager:Connectting()
Facebook.Unity.CallbackManager:TryCallCallback(Object, IResult)
Facebook.Unity.CallbackManager:CallCallback(Object, IResult)
Facebook.Unity.CallbackManager:OnFacebookResponse(IInternalResult)
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)
facebook-LinkWithCredentialAsync encountered an error: System.AggregateException: Exception of type 'System.AggregateException' was thrown.
-----------------
Firebase.FirebaseException: [ERROR_PROVIDER_ALREADY_LINKED] - User can only be linked to one identity for the given provider.
System.Threading.Tasks.<ContinueWith>c__AnonStorey0:<>m__0(Task)
System.Threading.Tasks.<ContinueWith>c__AnonStorey2:<>m__0(Task)
System.Threading.Tasks.<ContinueWith>c__AnonStorey1:<>m__0()
System.Threading.Tasks.Task:<immediateExecutor>m__1(Action)
System.Threading.Tasks.Task`1:RunContinuations()
System.Threading.Tasks.Task`1:TrySetException(AggregateException)
System.Threading.Tasks.TaskCompletionSource`1:SetException(Exception)
Firebase.Auth.<GetTask>c__AnonStorey0:<>m__0()
Firebase.Auth.Future_User:SWIG_CompletionDispatcher(Int32)
Firebase.AppUtil:PollCallbacks()
Firebase.Platform.FirebaseHandler:Update()
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)
2021-04-16 10:23:01.367311+0900 firebaseProject[1006:67777] [tcp] tcp_input [C23.1:3] flags=[R] seq=3109184249, ack=0, win=0 state=CLOSED rcv_nxt=3109184249, snd_una=2797527191
2021-04-16 10:23:01.367444+0900 firebaseProject[1006:67777] [tcp] tcp_input [C23.1:3] flags=[R] seq=3109184249, ack=0, win=0 state=CLOSED rcv_nxt=3109184249, snd_una=2797527191
facebook firebase success! :D 5ThQ■■■■■■■■■■■■■■
<TryFacebookFirebaseLogin>c__Iterator0:<>m__0(Task`1)
System.Threading.Tasks.<ContinueWith>c__AnonStorey0:<>m__0(Task)
System.Threading.Tasks.<ContinueWith>c__AnonStorey2:<>m__0(Task)
System.Threading.Tasks.<ContinueWith>c__AnonStorey1:<>m__0()
System.Threading.Tasks.Task:<immediateExecutor>m__1(Action)
System.Threading.Tasks.Task`1:RunContinuations()
System.Threading.Tasks.Task`1:TrySetResult(T)
System.Threading.Tasks.TaskCompletionSource`1:SetResult(T)
System.Threading.Tasks.<ContinueWith>c__AnonStorey0:<>m__0(Task)
System.Threading.Tasks.<ContinueWith>c__AnonStorey2:<>m__0(Task)
System.Threading.Tasks.<ContinueWith>c__AnonStorey1:<>m__0()
System.Threading.Tasks.Task:<immediateExecutor>m__1(Action)
System.Threading.Tasks.Task`1:RunContinuations()
System.Threading.Tasks.Task`1:TrySetResult(T)
System.Threading.Tasks.TaskCompletionSource`1:SetResult(T)
Firebase.Auth.<GetTask>c__AnonStorey0:<>m__0()
Firebase.Auth.Future_User:SWIG_CompletionDispatcher(Int32)
Firebase.AppUtil:PollCallbacks()
Firebase.Platform.FirebaseHandler:Update()
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)
Just in case if you wanna know. There are 1 providerID at this account
facebook.com
FirebaseAuth:DoesProvierExist(String)
<TryFacebookFirebaseLogin>c__Iterator0:<>m__0(Task`1)
System.Threading.Tasks.<ContinueWith>c__AnonStorey0:<>m__0(Task)
System.Threading.Tasks.<ContinueWith>c__AnonStorey2:<>m__0(Task)
System.Threading.Tasks.<ContinueWith>c__AnonStorey1:<>m__0()
System.Threading.Tasks.Task:<immediateExecutor>m__1(Action)
System.Threading.Tasks.Task`1:RunContinuations()
System.Threading.Tasks.Task`1:TrySetResult(T)
System.Threading.Tasks.TaskCompletionSource`1:SetResult(T)
System.Threading.Tasks.<ContinueWith>c__AnonStorey0:<>m__0(Task)
System.Threading.Tasks.<ContinueWith>c__AnonStorey2:<>m__0(Task)
System.Threading.Tasks.<ContinueWith>c__AnonStorey1:<>m__0()
System.Threading.Tasks.Task:<immediateExecutor>m__1(Action)
System.Threading.Tasks.Task`1:RunContinuations()
System.Threading.Tasks.Task`1:TrySetResult(T)
System.Threading.Tasks.TaskCompletionSource`1:SetResult(T)
Firebase.Auth.<GetTask>c__AnonStorey0:<>m__0()
Firebase.Auth.Future_User:SWIG_CompletionDispatcher(Int32)
Firebase.AppUtil:PollCallbacks()
Firebase.Platform.FirebaseHandler:Update()
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)
ClickButton (LogInBtn)(04/16/2021 10:23:11)
UIEventButtonClick:OnClick()
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)
firebase apple in
<TryAppleFirebaseLogin>c__Iterator1:MoveNext()
UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)
UIC_OptionPanel:_LinkMobilePlatform(E_MESSAGEBOX_CONFIRM_TYPE)
Messenger`1:Broadcast(String, T, MessengerMode)
UIC_MessageBox_Button:OnClick()
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)
-> applicationWillResignActive()
-> applicationDidBecomeActive()
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)
apple firebase success! :D 5ThQ■■■■■■■■■■■■■■
<TryAppleFirebaseLogin>c__AnonStorey3:<>m__0(ICredential)
AppleAuth.CallbackHandler:ExecutePendingCallbacks()
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)
Just in case if you wanna know. There are 1 providerID at this account
facebook.com
FirebaseAuth:DoesProvierExist(String)
<TryAppleFirebaseLogin>c__AnonStorey3:<>m__0(ICredential)
AppleAuth.CallbackHandler:ExecutePendingCallbacks()
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)
解决方案
所以...我发现对我正在做的事情缺乏了解是非常错误的...
我使用了来自 github 的 lupidan 的apple-signin-unity,并混合了我可以在 google 上找到的各种教程,以期望它可以正常工作。:|
Firebase 阻止链接多个已注册的帐户。我的只是处理以前的 FirebaseAuth 并覆盖新的。这就是为什么它看起来像是合并实际上没有做任何事情的帐户的原因。
在我提问之前我应该更加小心。
编辑:实际发生的事情是苹果登录也不例外。其他人使用“ContinueWith”功能有例外,但苹果没有。通过添加它,一切正常。
推荐阅读
- python - 用他们的分数打印球员
- r - 如何在特定阈值后替换列其余部分的值?
- react-native - 我想在反应原生的选择器中显示 json 数据。我正在使用基于功能的组件而不是基于类。有什么解决办法吗?
- python - 为什么 Beautiful Soup 将“<”视为无效字符?
- ios - Objective C - 使用自己的样式从 HTML 文本更改属性字符串的字体
- javascript - 如何从 typescript/javascript 中的对象数组中提取具有值的特定键?
- junit - @DataJpaTest 期间自动装配的 ObjectMapper 为空
- android - 如何使用工具栏而不是操作栏将旧的导航抽屉片段代码升级为代码?
- reactjs - 分阶段实施 React,怎么可能?
- go - 谷歌表格数据到 json