如何在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 } }
- 现在,用户在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") }
-
由于用户已经有了这个电子邮件地址的帐户,他现在正试图用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) } }) }
-
这样,您将在Firebase控制台中获得以下结果:
Firebase文档: https ://firebase.google.com/docs/auth/ios/account-linking
将身份validation提供程序凭据链接到用户帐户
将身份validation提供程序凭据链接到现有的用户帐户:
1.使用任何身份validation提供程序或方法login用户。
- 完成新身份validation提供程序的loginstream程,但不包括调用FIRAuth.signInWith方法之一。 例如,获取用户的Google ID令牌,Facebook访问令牌或电子邮件和密码。
- 获取新的身份validation提供程序的FIRAuthCredential