如何在Firebase中pipe理用户的不同身份validation

请在下列情况下帮助我find正确的解决scheme。

我正在用swift开发ios应用程序,它将使用Firebase作为后端。

用户应该能够通过电子邮件/密码或/和脸书login到firebase。 也许谷歌将在稍后添加。

对于每个真实用户有一个Firebase帐户是非常重要的,因为用户将有奖励积分,并且如果在一个devise(使用电子邮件login),他将拥有X个积分并且在其他设备(带有Facebook)上,会有不同的观点。

这里是我用来login电子邮件的代码:

//EMAIL REGISTER @IBAction func registerAction(_ sender: Any) { if self.emailTextField.text == "" || self.passwordTextField.text == "" { Print( "Please enter email and password.") } else { FIRAuth.auth()?.createUser(withEmail: self.emailTextField.text!, password: self.passwordTextField.text!, completion: { (user, error) in if error == nil { self.logoutButton.isHidden = false self.usernameLabel.text = user!.email self.emailTextField.text = "" self.passwordTextField.text = "" } else { Print("\((error?.localizedDescription)!)") } } ) } } //EMAIL LOGIN @IBAction func loginAction(_ sender: Any) { if self.emailTextField.text == "" || self.passwordTextField.text == "" { print( "Please enter email and password.") } else { FIRAuth.auth()?.signIn(withEmail: self.emailTextField.text!, password: self.passwordTextField.text!, completion: { (user, error) in if error == nil { self.logoutButton.isHidden = false self.usernameLabel.text = user!.email self.emailTextField.text = "" self.passwordTextField.text = "" } else { Print("\((error?.localizedDescription)!)") } }) } } 

这里是我用来loginFacebook的代码:

  func loginButton(_ loginButton: FBSDKLoginButton!, didCompleteWith result: FBSDKLoginManagerLoginResult!, error: Error!) { self.fbLoginButton.isHidden = true if error != nil { self.fbLoginButton.isHidden = false print(error.localizedDescription) return } else if (result.isCancelled) { print("canceled") self.fbLoginButton.isHidden = false } else { let credential = FIRFacebookAuthProvider.credential(withAccessToken: FBSDKAccessToken.current().tokenString) FIRAuth.auth()?.signIn(with: credential) { (user, error) in if let error = error { print(error.localizedDescription) return } } } } 

两种方法都可以正常工作,但他们创build了两个独立的帐户

它设置为允许多个用户使用相同的电子邮件设置: 在这里输入图像说明

最后我得到以下结果:

在这里输入图像说明

显然,我希望这两个帐户自动合并。

文档描述了如何链接auth提供程序,但用户应该使用一种方法login,只有在这之后才能链接帐户。 如果您已经拥有oauth凭证,则使用linkWithCredential方法。 如果用户使用电子邮件在一台设备上创build,如果他决定再次login其他设备上的Facebook,则无法工作。


用这些方法FIRAuth.auth()?.addStateDidChangeListener服务正在显示第二个视图控制器,我正在使用数据库。

重写func viewDidLoad(){super.viewDidLoad()

 let user = FIRAuth.auth()?.currentUser let dat = user?.providerData let email = user?.providerData[0].email let name = user?.displayName if email != nil { self.ref.child("user_profile").child("\(user!.uid)/email").setValue(email) } if name != { self.ref.child("user_profile").child("\(user!.uid)/name").setValue(name) } 

}

比方说,我们用facebooklogin,也许有可能find具有相同电子邮件的用户的UID并运行更新? 如果有很多用户,这个想法不是很好。

其他的想法是使用电子邮件作为id这样的:

self.ref.child("user_profile").child("\(email)/name").setValue(name)

不知道这是不是一个好的select?

感谢您的回复。

如何在第一个设备上使用他的电子邮件和密码login后使用不同的设备login用户,而无需匿名用户。

创build用户后,您需要将电子邮件和密码保存到NSUbiquitousKeyValueStore这样其他设备才能访问电子邮件和密码,因为您需要先login用户,然后再将其帐户链接到Facebook,如下所示。

在FB控制台中
1.帐户电子邮件地址设置: 防止使用同一电子邮件地址创build多个帐户这样,如果用户已经使用电子邮件地址login,则不会再次创build帐户。

2.如果用户select电子邮件地址作为第一次login:

  var iCloudKeyStore: NSUbiquitousKeyValueStore = NSUbiquitousKeyValueStore() FIRAuth.auth()?.createUser(withEmail: email, password: password) { (user, error) in // User created if error == nil{ // signed in successfully //Save the password and the email. Or choose your way to save them iCloudKeyStore.set(password, forKey: email) }else{ //Erorr } } 
  1. 现在,用户在Firebase中拥有一个帐户,并且看起来像这样:

在这里输入图像说明 4.现在在另一台设备上,用户决定用Facebook(不同的提供商)

使用Facebooklogin用户并获得fb令牌后:通常在FBSDKAccessTokenDidChange通知的函数侦听器中,使用Facebook令牌在Firebase上login用户。

 let credential = FIRFacebookAuthProvider.credential(withAccessToken: FBSDKAccessToken.current().tokenString) FIRAuth.auth()?.signIn(with: credential) { (user, error) in // ... if error != nil { // SETP 5. HERE let nsError = (error as! NSError) // Error: 17007 The email address is already in use by another account. ERROR_EMAIL_ALREADY_IN_USE if nsError.code == 17007{ print(error,user?.uid,nsError.code,"facebook user error") let email = nsError.userInfo["FIRAuthErrorUserInfoEmailKey"] as? String self.signInUserWithEmail(email: email!) print("email",email) } }else{ print(user!.uid,"facebook user login") } 
  1. 由于用户已经有了这个电子邮件地址的帐户,他现在正试图用Facebooklogin,所以会出现错误:正如您在步骤4中看到的,现在您需要先login用户,然后再链接到Facebook帐户:

     func signInUserWithEmail(email:String){ let password = iCloudKeyStore.string(forKey: email) FIRAuth.auth()?.signIn(withEmail: email, password: password, completion: { (user:FIRUser?, error:Error?) in if user != nil{ self.linkAccountWihtFacebook() print(user?.uid) }else{ print(error?.localizedDescription) } }) } 

    func linkAccountWihtFacebook(){

      let credential = FIRFacebookAuthProvider.credential(withAccessToken: FBSDKAccessToken.current().tokenString) FIRAuth.auth()?.currentUser?.link(with: credential, completion: { (user:FIRUser?, error:Error?) in if let LinkedUser = user{ print("NEW USER:",LinkedUser.uid) } if let error = error as? NSError{ //Indicates an attempt to link a provider of a type already linked to this account. if error.code == FIRAuthErrorCode.errorCodeProviderAlreadyLinked.rawValue{ print("FIRAuthErrorCode.errorCodeProviderAlreadyLinked") } //This credential is already associated with a different user account. if error.code == 17025{ } print("MyError",error) } }) } 
  2. 这样,您将在Firebase控制台中获得以下结果:

在这里输入图像说明

Firebase文档: https ://firebase.google.com/docs/auth/ios/account-linking

将身份validation提供程序凭据链接到用户帐户

将身份validation提供程序凭据链接到现有的用户帐户:

1.使用任何身份validation提供程序或方法login用户。

  1. 完成新身份validation提供程序的loginstream程,但不包括调用FIRAuth.signInWith方法之一。 例如,获取用户的Google ID令牌,Facebook访问令牌或电子邮件和密码。
  2. 获取新的身份validation提供程序的FIRAuthCredential