如何解决Facebook 身份验证“已存在具有相同电子邮件地址但登录凭据不同的帐户”
我有多个登录选项供用户选择:电子邮件、谷歌和 Facebook。如果 Firebase 已将电子邮件存储为用户(即用户之前使用 test@gmail.com 注册),则会出现一个提醒,告知用户使用该电子邮件的帐户已存在。这非常适用于 Google 登录,如此 screenshot 所示。但是,当用户单击 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,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,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 ?? "",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,_ 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,completion: nil)
print("Switched to TabBarController")
}
func setUpEmailButton() {
Utilities.styleDarkFilledButton(signInEmailButton)
}
} // end
我认为没有收到警报的原因是 Facebook uid 与 Firestore 中保存的电子邮件 uid 不匹配(而 Google uid 匹配)。我让警报显示的方式是 uid 是否与 Firestore 中的匹配,因此,警报不会显示。有谁知道我如何获得警报以显示如何不收到此错误?
我知道我的代码有点乱,所以如果你需要进一步的解释,请告诉我。任何帮助表示赞赏!
解决方法
经过数小时试图找出我的问题后,我决定发布一个问题......但几乎立即找到了答案(我知道是对的:/)。
由于已在项目设置中启用每封电子邮件一个帐户,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。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。