Join us for Firebase Summit on November 10, 2021. Tune in to learn how Firebase can help you accelerate app development, release with confidence, and scale with ease. Register

קשר ספקי אימות מרובים לחשבון ב- iOS

תוכל לאפשר למשתמשים להיכנס לאפליקציה שלך באמצעות ספקי אימות מרובים על ידי קישור אישורי ספק אישור לחשבון משתמש קיים. משתמשים ניתנים לזיהוי על ידי אותו מזהה משתמש של Firebase ללא קשר לספק האימות שבו השתמשו בכניסה. לדוגמה, משתמש שנכנס באמצעות סיסמה יכול לקשר חשבון Google ולהיכנס עם אחת השיטות בעתיד. לחלופין, משתמש אנונימי יכול לקשר חשבון פייסבוק ולאחר מכן להיכנס עם פייסבוק כדי להמשיך להשתמש באפליקציה שלך.

לפני שאתה מתחיל

הוסף לאפליקציה שלך תמיכה בשני ספקי אימות (או כולל אימות אנונימי).

כדי לקשר את אישורי ספק האישור לחשבון משתמש קיים:

  1. היכנס למשתמש באמצעות כל ספק או שיטת אימות.
  2. השלם את כניסת זרימה של ספק האימות החדש עד, אך לא כולל, קורא אחד FIRAuth.signInWith השיטות. לדוגמה, קבל את אסימון מזהה Google של המשתמש, אסימון הגישה לפייסבוק או דוא"ל וסיסמה.
  3. קבל FIRAuthCredential עבור ספק האימות החדש:

    כניסה ל- Google
    מָהִיר
    guard
      let authentication = user?.authentication,
      let idToken = authentication.idToken
    else {
      return
    }
    
    let credential = GoogleAuthProvider.credential(withIDToken: idToken,
                                                   accessToken: authentication.accessToken)
    
    Objective-C
    GIDAuthentication *authentication = user.authentication;
    FIRAuthCredential *credential =
    [FIRGoogleAuthProvider credentialWithIDToken:authentication.idToken
                                     accessToken:authentication.accessToken];
    
    כניסה לפייסבוק
    מָהִיר
    let credential = FacebookAuthProvider
      .credential(withAccessToken: AccessToken.current!.tokenString)
    
    Objective-C
    FIRAuthCredential *credential = [FIRFacebookAuthProvider
        credentialWithAccessToken:[FBSDKAccessToken currentAccessToken].tokenString];
    
    כניסה למייל באמצעות סיסמה
    מָהִיר
    let credential = EmailAuthProvider.credential(withEmail: email, password: password)
    
    Objective-C
    FIRAuthCredential *credential =
        [FIREmailAuthProvider credentialWithEmail:email
                                                 password:password];
    
  4. תעביר את FIRAuthCredential האובייקט אל שנכנסו לחשבון המשתמש linkWithCredential:completion: השיטה:

    מָהִיר
        user.link(with: credential) { authResult, error in
      // ...
    }
    }
    
    Objective-C
        [[FIRAuth auth].currentUser linkWithCredential:credential
        completion:^(FIRAuthDataResult *result, NSError *_Nullable error) {
      // ...
    }];
    

    קריאת linkWithCredential:completion: תיכשל אם את האישורים כבר מקושרים לחשבון משתמש אחר. במצב זה, עליך לטפל במיזוג החשבונות והנתונים המשויכים בהתאם לאפליקציה שלך:

    מָהִיר

    let prevUser = Auth.auth().currentUser
    Auth.auth().signIn(with: credential) { authResult, error in
        if let error = error {
          let authError = error as NSError
          if isMFAEnabled, authError.code == AuthErrorCode.secondFactorRequired.rawValue {
            // The user is a multi-factor user. Second factor challenge is required.
            let resolver = authError
              .userInfo[AuthErrorUserInfoMultiFactorResolverKey] as! MultiFactorResolver
            var displayNameString = ""
            for tmpFactorInfo in resolver.hints {
              displayNameString += tmpFactorInfo.displayName ?? ""
              displayNameString += " "
            }
            self.showTextInputPrompt(
              withMessage: "Select factor to sign in\n\(displayNameString)",
              completionBlock: { userPressedOK, displayName in
                var selectedHint: PhoneMultiFactorInfo?
                for tmpFactorInfo in resolver.hints {
                  if displayName == tmpFactorInfo.displayName {
                    selectedHint = tmpFactorInfo as? PhoneMultiFactorInfo
                  }
                }
                PhoneAuthProvider.provider()
                  .verifyPhoneNumber(with: selectedHint!, uiDelegate: nil,
                                     multiFactorSession: resolver
                                       .session) { verificationID, error in
                    if error != nil {
                      print(
                        "Multi factor start sign in failed. Error: \(error.debugDescription)"
                      )
                    } else {
                      self.showTextInputPrompt(
                        withMessage: "Verification code for \(selectedHint?.displayName ?? "")",
                        completionBlock: { userPressedOK, verificationCode in
                          let credential: PhoneAuthCredential? = PhoneAuthProvider.provider()
                            .credential(withVerificationID: verificationID!,
                                        verificationCode: verificationCode!)
                          let assertion: MultiFactorAssertion? = PhoneMultiFactorGenerator
                            .assertion(with: credential!)
                          resolver.resolveSignIn(with: assertion!) { authResult, error in
                            if error != nil {
                              print(
                                "Multi factor finanlize sign in failed. Error: \(error.debugDescription)"
                              )
                            } else {
                              self.navigationController?.popViewController(animated: true)
                            }
                          }
                        }
                      )
                    }
                  }
              }
            )
          } else {
            self.showMessagePrompt(error.localizedDescription)
            return
          }
          // ...
          return
        }
        // User is signed in
        // ...
    }
                // Merge prevUser and currentUser accounts and data
                // ...
            }
    

    Objective-C

    FIRUser *prevUser = [FIRAuth auth].currentUser;
    [[FIRAuth auth] signInWithCredential:credential
                              completion:^(FIRAuthDataResult * _Nullable authResult,
                                           NSError * _Nullable error) {
        if (isMFAEnabled && error && error.code == FIRAuthErrorCodeSecondFactorRequired) {
          FIRMultiFactorResolver *resolver = error.userInfo[FIRAuthErrorUserInfoMultiFactorResolverKey];
          NSMutableString *displayNameString = [NSMutableString string];
          for (FIRMultiFactorInfo *tmpFactorInfo in resolver.hints) {
            [displayNameString appendString:tmpFactorInfo.displayName];
            [displayNameString appendString:@" "];
          }
          [self showTextInputPromptWithMessage:[NSString stringWithFormat:@"Select factor to sign in\n%@", displayNameString]
                               completionBlock:^(BOOL userPressedOK, NSString *_Nullable displayName) {
           FIRPhoneMultiFactorInfo* selectedHint;
           for (FIRMultiFactorInfo *tmpFactorInfo in resolver.hints) {
             if ([displayName isEqualToString:tmpFactorInfo.displayName]) {
               selectedHint = (FIRPhoneMultiFactorInfo *)tmpFactorInfo;
             }
           }
           [FIRPhoneAuthProvider.provider
            verifyPhoneNumberWithMultiFactorInfo:selectedHint
            UIDelegate:nil
            multiFactorSession:resolver.session
            completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) {
              if (error) {
                [self showMessagePrompt:error.localizedDescription];
              } else {
                [self showTextInputPromptWithMessage:[NSString stringWithFormat:@"Verification code for %@", selectedHint.displayName]
                                     completionBlock:^(BOOL userPressedOK, NSString *_Nullable verificationCode) {
                 FIRPhoneAuthCredential *credential =
                     [[FIRPhoneAuthProvider provider] credentialWithVerificationID:verificationID
                                                                  verificationCode:verificationCode];
                 FIRMultiFactorAssertion *assertion = [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
                 [resolver resolveSignInWithAssertion:assertion completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
                   if (error) {
                     [self showMessagePrompt:error.localizedDescription];
                   } else {
                     NSLog(@"Multi factor finanlize sign in succeeded.");
                   }
                 }];
               }];
              }
            }];
         }];
        }
      else if (error) {
        // ...
        return;
      }
      // User successfully signed in. Get user data from the FIRUser object
      if (authResult == nil) { return; }
      FIRUser *user = authResult.user;
      // ...
    }];
                                        // Merge prevUser and currentUser accounts and data
                                        // ...
                                    }];
    

אם קריאת linkWithCredential:completion: מצליחה, המשתמש יכול כעת להתחבר באמצעות כול ספק אימות מקושרות וגישה לנתונים באותו Firebase.

תוכל לבטל את הקישור של ספק אישור מחשבון, כך שהמשתמש לא יוכל להיכנס עוד עם ספק זה.

לביטול קישור ספק auth מחשבון משתמש, לעבור הספק מזהה את unlinkFromProvider:completion: שיטה. אתה יכול לקבל את תעודות הזהות ספקית של ספקי auth קשורה משתמש מ- providerData רכוש.

מָהִיר

Auth.auth().currentUser?.unlink(fromProvider: providerID!) { user, error in
  // ...
}

Objective-C

[[FIRAuth auth].currentUser unlinkFromProvider:providerID
                                    completion:^(FIRUser *_Nullable user, NSError *_Nullable error) {
  // ...
}];