2016-12-29 100 views
2

請在下列情況下幫助我找到正確的解決方案。如何在Firebase中管理用戶的不同身份驗證

我正在用swift開發ios應用程序,它將使用Firebase作爲後端。

用戶應該能夠通過電子郵件/密碼或/和臉書登錄到firebase。也許谷歌將在稍後添加。

對於每個真實用戶擁有一個Firebase帳戶非常重要,因爲用戶將獲得獎勵積分,並且如果在一個設計中(使用電子郵件登錄),他將擁有X個積分並且在其他設備上與臉譜)他會有不同的觀點。

這裏是代碼,我使用的電子郵件登錄:

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

       } 
      }) 
     } 
    } 

這裏是我使用與Facebook登錄代碼:

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

這兩種方法都做工精細,但他們創造兩個獨立的賬戶。

它設置爲允許多個用戶使用同一個電子郵件中設置: enter image description here

和我結束了以下結果:

enter image description here

很明顯,我想這兩個帳戶自動合併。

Documentation描述瞭如何鏈接auth提供程序的方式,但用戶應該使用一種方法登錄並且只有在該方法之後才能鏈接帳戶。 linkWithCredential方法用於已經擁有oauth憑證的情況。如果用戶使用電子郵件在一臺設備上創建,如果他決定再次在其他設備上使用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) 
} 

}

讓我們說,我們洛與Facebook,也許就可以找到用戶的UID具有相同的電子郵件和運行更新?萬一有很多用戶,這不是一個好主意。

其他想法是使用電子郵件作爲ID這樣的:

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

不知道這是一個很好的選擇嗎?

感謝您的回覆。

回答

1

如何在第一臺沒有匿名用戶的設備上使用他的電子郵件和密碼登錄後,使用不同設備登錄用戶。

創建用戶後,您需要將電子郵件和密碼保存爲NSUbiquitousKeyValueStore,這樣其他設備才能訪問電子郵件和密碼,因爲您需要首先登錄用戶,然後才能將其帳戶鏈接到Facebook下面。

在FB控制檯
1.帳戶電子郵件地址設置:防止創建多個賬戶使用相同的電子郵件地址這樣該帳戶沒有得到,如果已經與電子郵件地址登錄的用戶再次創造的。

2.如果用戶選擇電子郵件地址作爲第一登錄:

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 
      } 
     } 
  • 現在用戶擁有帳戶在火力地堡和將看起來像:
  • enter image description here 4.現在其他設備上的用戶決定與Facebook(不同提供商)

    登錄您在用戶與Facebook和簽訂後有fb令牌:通常在FBSDKAccessTokenDidChange通知的函數偵聽器中,您使用Facebook的令牌在Firebase中登錄用戶。

    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") 
        } 
    
  • 由於用戶已經使用此電子郵件地址,他現在試圖與Facebook的帳戶,這樣的錯誤會發生:如您在步驟4中看到,現在你需要您鏈接之前帳戶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) 
          } 
    
         }) 
    } 
    
  • 這樣,您將在火力地堡控制檯以下結果:

  • enter image description here

    火力地堡文檔: https://firebase.google.com/docs/auth/ios/account-linking

    鏈接身份驗證提供憑據的用戶帳戶

    將身份驗證提供程序憑據鏈接到現有用戶帳戶:

    1.使用任何身份驗證提供程序或方法登錄用戶。

    1. 完成新認證提供者的登錄流程,但不包括調用FIRAuth.signInWith方法之一。 例如,獲取用戶的Google ID令牌,Facebook訪問令牌或 電子郵件和密碼。
    2. 找一個FIRAuthCredential爲新的身份驗證提供
    +0

    嗨,如果我選擇防止多ACCS的創作......我用電子郵件和密碼創建的帳戶後,我不能用Facebook登錄。 (因爲電子郵件是相同的)。我使用的是與您通過電子郵件和密碼登錄相同的代碼。或者我錯過了什麼? – Almazini

    +0

    可以說我已經有一個電子郵件和密碼帳戶。我想在其他設備上使用Facebook登錄。我想登錄到現有用戶而不是創建新用戶。 – Almazini

    +0

    生病編輯我的答案... – Jad

    相關問題