Facebook Auth "An account already exists with the same email address but different sign-in credentia



我有多个登录选项供用户选择:电子邮件、谷歌和脸书。如果Firebase已经将电子邮件存储为用户(即之前注册的用户test@gmail.com),一个警报,告诉用户已存在该电子邮件的帐户。这非常适用于谷歌登录,如此屏幕截图所示。然而,当用户点击Facebook按钮(甚至不切换屏幕(时,视觉上什么都不会发生,我在调试器中得到了这个错误:

Error Domain=FIRAuthErrorDomain Code=17012 "An account already exists with
the same email address but different sign-in credentials. Sign in using a
provider associated with this email address." UserInfo={FIRAuthErrorUserInfoNameKey=ERROR_ACCOUNT_EXISTS_WITH_DIFFERENT_CREDENTIAL,
FIRAuthErrorUserInfoEmailKey=318junkjabr@gmail.com,
FIRAuthErrorUserInfoUpdatedCredentialKey=<FIROAuthCredential:
0x6000005f3200>, NSLocalizedDescription=An account already exists with the
same email address but different sign-in credentials. Sign in using a
provider associated with this email address.}

这是我的登录视图控制器代码:

override func viewDidLoad() {
super.viewDidLoad()

setUpFBButton()
setUpGoogleButton()
setUpEmailButton()

GIDSignIn.sharedInstance()?.presentingViewController = self
}



// MARK: - SIGN UP WITH GOOGLE
func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) {

if let err = error {
print("Failed to log into Google: ", err)
return
}
print("Successfully logged into Google")

guard let authentication = user.authentication else { return }
let credential = GoogleAuthProvider.credential(withIDToken: authentication.idToken, accessToken: authentication.accessToken)

// sign user in with Firebase
Auth.auth().signIn(with: credential, completion: { (user, error) in
let firstName = user?.user.displayName
let email = user?.user.email
let lastName = ""
let uid = user?.user.uid

if let err = error {
print("Failed to create a Firebase User with Google account: ", err)
return
} else {
// Successfully logged in
print("Successfully logged into Firebase with Google email: ", email ?? "", "Now add user to Firestore if user is new.")

// check if user already exists
self.addUserToFirestore(firstName ?? "", lastName, email ?? "", uid ?? "", "Google")
}
})
}


fileprivate func setUpGoogleButton() {
Utilities.styleLightFilledButton(signInGoogleButton)
signInGoogleButton!.addTarget(self, action:
#selector(handleCustomGoogleSignIn), for: .touchUpInside)

GIDSignIn.sharedInstance()?.delegate = self
}

@objc func handleCustomGoogleSignIn() {
GIDSignIn.sharedInstance().signIn()
}




// MARK: - SIGN UP WITH FACEBOOK

// design the facebook button and assign #selector to facebook button actions
fileprivate func setUpFBButton() {
Utilities.styleHollowButton(signInFacebookButton)

signInFacebookButton.addTarget(self, action: #selector(handleCustomFBButton), for: .touchUpInside)
}

// handle the facebook button actions
@objc func handleCustomFBButton() {
LoginManager().logIn(permissions: ["email", "public_profile"], from: self) { (result, err) in
if err != nil {
print("Custom FB login failed:", err!)
return
}
self.getUserInfo()
}
}

// grab id, name, and email of user
func getUserInfo() {
print("Successfully logged in with facebook...")
GraphRequest(graphPath: "/me", parameters: ["fields": "id, name, email"]).start {
(connection, result, err) in
guard let Info = result as? [String: Any] else { return }
let name = Info["name"] as? String
let email = Info["email"] as? String
let uid = Info["id"] as? String

if err != nil {
print("Failed to start graph request:", err!)
return
}
print(result!)
self.signIntoFirebase(name ?? "", email ?? "", uid ?? "")

}
}

// connect the user to firebase
func signIntoFirebase(_ name:String, _ email:String, _ uid:String) {
let credential = FacebookAuthProvider.credential(withAccessToken: AccessToken.current!.tokenString)
Auth.auth().signIn(with: credential) { (user, error) in
if let err = error {
print(err)
return
} else {
print("Facebook user successfully authenticated with Firebase. Now run through Firestore.")
// check if user already exists. if user exists, go to chats screen. if it does not exist, create a new user and redirect to chat screen.
self.addUserToFirestore(name, "", email, uid, "Facebook")

}
}
}


func loginButtonDidLogOut(_ loginButton: FBLoginButton) {
print("Logged out of facebook")
}



// MARK: - Other functions

func addUserToFirestore(_ firstName:String, _ lastName:String, _ email:String, _ uid:String, _ signInMethod:String) {
let db = Firestore.firestore()
let docRef = db.collection("users").document(uid)
// check if user exists in firestore
docRef.getDocument { (document, error) in
if let document = document {
if document.exists {
let message = "Good news! You already have a Coal account that uses " + email + ".nPlease sign in to your existing account. Then you will be able to link your " + signInMethod + " profile from your Account Settings page."
// user exists. send to chats screen.
print("User already exists. Document data: (String(describing: document.data()))")
self.showError("You're already a member!", message)
} else {
// user does not exist. create a new user
print("Document does not exist. Create new user.")

docRef.setData(["firstname":firstName, "lastname":lastName, "email":email]) { err in
if err != nil {
// Show error message
print("Error saving user data to Firestore")
} else {
print("New user created in Firestore")
self.transitionToConvo()
}
}
}
}
}
}

func showError(_ title:String, _ message:String) {

let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertController.Style.alert)
alert.addAction(UIAlertAction(title: "Ok", style: UIAlertAction.Style.default, handler: nil))
self.present(alert, animated: true, completion: nil)
}

func transitionToConvo() {
let tabBarC = self.storyboard?.instantiateViewController(withIdentifier: "mainTabBarController") as! TabBarController
tabBarC.modalPresentationStyle = .fullScreen
self.present(tabBarC, animated: true, completion: nil)
print("Switched to TabBarController")
}

func setUpEmailButton() {
Utilities.styleDarkFilledButton(signInEmailButton)
}


} // end

我认为它没有收到警报的原因是Facebook的uid与Firestore中保存的电子邮件uid不匹配(而谷歌的uid确实匹配(。我显示警报的方式是,如果uid与Firestore中的uid匹配,那么警报就不会显示。有人知道我如何获得警报以显示如何避免出现此错误吗?

我知道我的代码有点乱,所以如果你需要进一步的解释,请告诉我。感谢您的帮助!!

经过几个小时的努力,我决定发布一个问题。。。但几乎紧接着,我找到了答案(我知道得对:/(。

由于在项目设置中已启用每个电子邮件一个帐户,因此Auth.auth().signIn会自动扫描用户是否存在。如果用户存在,它将在if error != nil之后返回一个错误。因为它在调用我的addUserToFirestore函数之前返回了一个错误(检查用户是否存在,如果不存在,则将用户添加到Firestore(,所以从未显示警报。

既然我们知道了if error != nil的意思,我们就可以在那里插入警报:

Auth.auth().signIn(with: credential) { (user, error) in
if error != nil {
let message = "Good news! You already have a Coal account that uses " + email + ".nPlease sign in to your existing account. Then you will be able to link your Facebook profile from your Account Settings page."
// user exists. send to chats screen.
print("User already exists. Let user know.")
self.showError("You're already a member!", message)
return
}

我不知道为什么它适用于Google Auth,但最终它就是适用于Facebook Auth的。

相关内容

最新更新