2016-12-29 2 views
2

verwalten bitte helfen Sie mir, richtige Lösung in der folgenden Situation zu finden.Wie man Benutzer unterschiedliche Authentifizierung in Firebase

Ich entwickle iOS-App mit Swift, die Firebase als Backend verwenden wird.

Benutzer sollten sich in Firebase mit E-Mail/Passwort oder/und mit Facebook einloggen können. Vielleicht wird Google später hinzugefügt.

Es ist wichtig für jeden echten Benutzer ein Firebase-Konto zu haben, da der Benutzer Bonuspunkte hat und es keinen Sinn ergibt, wenn er auf einem Gerät (mit Email-Login) X-Punkte und auf einem anderen Gerät hat (mit facebook) wird er verschiedene Punkte haben.

Hier ist der Code, den ich mit E-Mail anmelden bin mit:

//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)!)") 

       } 
      }) 
     } 
    } 

Hier ist der Code, den ich mit Facebook anmelden bin mit:

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 
       } 
      } 
     } 
    } 

Beide Methoden funktionieren, aber sie schaffen zwei getrennte Konten.

Es ist eingerichtet, um mehrere Benutzer mit der gleichen E-Mail in den Einstellungen zu erlauben: enter image description here

und ich am Ende mit folgendem Ergebnis:

enter image description here

Offensichtlich mag ich diese beiden Konten automatisch zusammengeführt werden.

Documentation beschreibt die Art, wie Auth-Provider zu verknüpfen, aber Benutzer sollten mit einer Methode angemeldet sein und erst danach wird es möglich sein, Konten zu verknüpfen. linkWithCredential Methode wird verwendet, wenn Sie bereits die oauth-Berechtigung besitzen. Falls der Benutzer auf einem Gerät mit E-Mail erstellt wurde, funktioniert es nicht, wenn er sich wieder auf einem anderen Gerät mit Facebook anmeldet.


Nachdem er mit einem dieser Wege loggin in der FIRAuth.auth()?.addStateDidChangeListener Service zweite View-Controller zeigt, wo ich mit Datenbank arbeiten werde.

Überschreibung 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) 
} 

}

Let sagen wir mit Facebook loggin, vielleicht ist es möglich, UID des Benutzers mit derselben E-Mail zu finden und Updates laufen ? Nicht sehr gute Idee, wenn es viele Benutzer gibt.

Andere Idee ist, E-Mail, id wie folgt zu verwenden:

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

Nicht sicher, ob es eine gute Option ist?

danke für Ihre Antworten.

Antwort

1

So melden Sie sich bei einem Benutzer von einem anderen Gerät an, nachdem er sich mit der E-Mail-Adresse und dem Passwort auf dem ersten Gerät ohne anonyme Benutzer angemeldet hat.

Nachdem Sie den Benutzer erstellt haben, müssen Sie die E-Mail und das Passwort auf NSUbiquitousKeyValueStore speichern. Auf diese Weise erhält das andere Gerät Zugriff auf E-Mail und Passwort, da Sie den Benutzer zuerst anmelden müssen, bevor Sie sein Konto mit Facebook verknüpfen unten.

In FB-Konsole
1. Konto E-Mail-Adresse Einstellungen: Prevent Erstellung mehrerer Konten mit derselben E-Mail-Adresse diese Weise wird das Konto nicht wieder erstellt wird erhalten, wenn der Benutzer bereits mit E-Mail-Adresse angemeldet.

2. Wenn der Benutzer E-Mail-Adresse als erste Anmeldung wählen:

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. nun der Benutzer ein Konto in Firebase hat und wird so aussehen:

enter image description here 4. Jetzt auf dem anderen Gerät entschied sich der Benutzer mit Facebook (verschiedene Anbieter)

Nachdem Sie in den Benutzer mit Facebook unterzeichnet haben, um sich einzuloggen und Habe fbs Token: Normalerweise im Listener der Funktion von FBSDKAccessTokenDidChange Notification, melden Sie den Benutzer mit Firebase mit Facebook-Token an.

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. Da der Benutzer bereits ein Konto mit dieser E-Mail-Adresse hat, die er jetzt mit Facebook anmelden versucht, so wird ein Fehler auftritt: wie Sie in Schritt siehe 4 , jetzt müssen Sie in den Benutzer anmelden, bevor Sie Konto auf Facebook Link lautet:

    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. Auf diese Weise erhalten Sie das folgende Ergebnis in Firebase-Konsole:

enter image description here

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

Link-Auth-Provider-Anmeldeinformationen zu einem Benutzerkonto

So verknüpfen Sie die Anmeldeinformationen des Authentifizierungsanbieters mit einem vorhandenen Benutzerkonto:

1. Melden Sie sich mit einem Authentifizierungsanbieter oder einer Methode an.

  1. Füllen Sie den Anmeldevorgang für den neuen Authentifizierungsanbieter bis zum Aufruf einer der Methoden FIRAuth.signInWith, jedoch nicht einschließlich. Erhalten Sie beispielsweise das Google-ID-Token des Nutzers, das Facebook-Zugriffstoken oder die E-Mail-Adresse und das Passwort .
  2. eine FIRAuthCredential für die neuen Authentifizierungsanbieter Get
+0

Hallo, wenn ich die Erstellung mehrerer accs verhindern wählen ... Ich kann nicht mit Facebook anmelden, nachdem ich mit E-Mail und Passwort-Konto erstellt. (weil E-Mail dasselbe ist). Ich benutze den gleichen Code, den Sie für die Anmeldung mit E-Mail & Passw geschrieben haben. Oder ich vermisse etwas? – Almazini

+0

Sagen wir, ich habe bereits einen Account mit Email und Passwort. Und ich möchte mich mit Facebook auf einem anderen Gerät anmelden. Und ich möchte mich bei bestehenden Benutzern anmelden, ohne neue zu erstellen. – Almazini

+0

Ill edit meine Antwort ... – Jad

Verwandte Themen