当具有相同电子邮件地址的帐户已存在时,尝试使用FB登录凭据登录Firebase身份验证帐户时遇到困难。最终,我想将两个身份验证提供程序链接到同一个Firebase用户帐户,但是目前我无法获得FB凭据(如果已经存在)使用以下代码登录Firebase(如果已经存在),我认为该代码完全遵循Firebase文档。我已经限制了单个用户(电子邮件)具有基于Auth Provider的多个帐户的功能。当我删除“原始” Firebase用户帐户时,Facebook登录名能够按预期的方式登录并创建用户帐户,因此,仅当已经有来自其他身份验证提供商的具有相同电子邮件地址的Firebase身份验证帐户时,问题才会出现。 >
场景
在我测试的场景中,我已经创建了一个电子邮件/密码帐户(原始),并试图通过FB登录(使用与电子邮件/密码帐户相同的电子邮件地址)添加我的FB帐户。原始帐户。我可以获取FB AccessToken和FB凭据,但是当我将其传递给Auth.auth()。sign(with:credential .....时,它总是会出错,并出现以下错误:
错误
错误域= FIRAuthErrorDomain代码= 17012“帐户已经存在,具有相同的电子邮件地址,但登录凭据不同。请使用与此电子邮件地址关联的提供商进行登录。 UserInfo = {FIRAuthErrorUserInfoNameKey = ERROR_ACCOUNT_EXISTS_WITH_DIFFERENT_CREDENTIAL,FIRAuthErrorUserInfoEmailKey=akash11x@gmail.com,FIRAuthErrorUserInfoUpdatedCredentialKey =,NSLocalizedDescription =已存在具有相同电子邮件地址但登录凭据不同的帐户。使用与此电子邮件地址关联的提供商登录。
代码
@IBAction func fbLoginButton(_ sender: FBButton) {
let loginManager = LoginManager()
loginManager.logIn(permissions: ["public_profile", "email"], from: self) { (result, error) in
if error != nil {
return
}
print(result)
guard let accessToken = AccessToken.current else {
print("Failed to get access token")
return
}
print(accessToken)
let credential = FacebookAuthProvider.credential(withAccessToken: accessToken.tokenString)
print(credential)
Auth.auth().signIn(with: credential, completion: { (firebaseUser, error) in //Can't get passed this point when another account with the same email address already exists
if error != nil {
print("Could not login into Firebase using FB credentials")
return
}
print("This is the FirebaseUser after FB Login: \(firebaseUser)")
firebaseUser?.user.link(with: credential, completion: { (authResult, error) in
if error != nil {
print("Firebase Auth Providers not linked")
return
}
// let prevUser = Auth.auth().currentUser
// Auth.auth().signIn(with: credential) { (authResult, error) in
// if let error = error {
// // ...
// return
// }
// // User is signed in
// // ...
// }
// // Merge prevUser and currentUser accounts and data
//
// ...
//This user has a profile, go to tab controller
let tabBarVC = self.storyboard?.instantiateViewController(withIdentifier: Constants.Storyboard.tabBarController)
self.view.window?.rootViewController = tabBarVC
self.view.window?.makeKeyAndVisible()
})
})
}
}
答案 0 :(得分:0)
万一其他人遇到同样的问题。
通过使用登录流程,使新的身份验证提供程序具有与现有Firebase身份验证帐户相同的电子邮件地址,似乎无法“实时”链接Firebase身份验证提供程序。因此,我的解决方案是在他们使用电子邮件/密码登录后在个人资料中创建“将Facebook链接到您的个人资料”按钮。然后,该按钮在Firebase中创建链接,以将facebook识别为该帐户的辅助身份验证提供程序。为了进行测试,我注销并使用了“使用Facebook登录”按钮,所有操作均按预期进行。
我认为此UX大大降低了该功能的实用性,但经过数周的研究,我能得出最好的结果。
个人资料上的代码以将Facebook链接到电子邮件/密码原始帐户
@IBAction func fbLoginButton(_ sender: FBButton) {
let loginManager = LoginManager()
loginManager.logIn(permissions: ["public_profile", "email"], from: self) { (result, error) in
if error != nil {
return
}
print(result)
guard let accessToken = AccessToken.current else {
print("Failed to get access token")
return
}
print(accessToken)
let credential = FacebookAuthProvider.credential(withAccessToken: accessToken.tokenString)
print(credential)
if let user = Auth.auth().currentUser {
print("This is the user: \(user)")
// [START link_credential]
user.link(with: credential) { _, error in
// [START_EXCLUDE]
if let error = error {
print("FB did not link to account. \(error)")
return
}
}
}
}
}
登录页面上的代码(如下),电子邮件/密码登录
别忘了将LoginButtonDelegate添加到视图控制器
@IBAction func fbLoginButton(_ sender: FBButton) {
let loginManager = LoginManager()
loginManager.logIn(permissions: ["public_profile", "email"], from: self) { (result, error) in
if error != nil {
return
}
guard let accessToken = AccessToken.current else {
print("Failed to get access token")
return
}
let credential = FacebookAuthProvider.credential(withAccessToken: accessToken.tokenString)
Auth.auth().signIn(with: credential) { (authResult, error) in
if let error = error {
// ...
return
}
let user = authResult?.user
//Check if user is nill
if user != nil {
//This means that we have a user, now check if they have a User document
UserService.getUserProfile() { (u) in
if u == nil {
//No profile, go to Profile Controller
self.performSegue(withIdentifier: Constants.Segue.profileViewController, sender: self)
}
else {
//Save the logged in user to local storage
LocalStorageService.saveCurrentUser(user: u!)
//This user has a profile, go to tab controller
let tabBarVC = self.storyboard?.instantiateViewController(withIdentifier: Constants.Storyboard.tabBarController)
self.view.window?.rootViewController = tabBarVC
self.view.window?.makeKeyAndVisible()
}
}
}
}
}
}
对于按钮本身,我在视图中使用情节提要添加了一个按钮,并使用了客户类“ FBSDKButton”并相应地设置了样式:
let fbButtonText = NSAttributedString(string: "Link facebook to Profile")
fbLoginButton.setAttributedTitle(fbButtonText, for: .normal)
和
let fbButtonText = NSAttributedString(string: "Login with facebook")
fbLoginButton.setAttributedTitle(fbButtonText, for: .normal)
最后,请确保您导入了适当的库;我用了: 导入FirebaseAuth 导入FBSDKCoreKit 导入FacebookCore 导入Facebook登录 导入FBSDKLoginKit 导入Firebase