ربط العديد من موفري المصادقة بحساب على iOS

يمكنك السماح للمستخدمين بتسجيل الدخول إلى تطبيقك باستخدام موفري مصادقة متعددين عن طريق ربط بيانات اعتماد موفر المصادقة بحساب مستخدم حالي. يمكن التعرف على المستخدمين من خلال نفس معرف مستخدم Firebase بغض النظر عن موفر المصادقة الذي استخدموه لتسجيل الدخول. على سبيل المثال ، يمكن للمستخدم الذي قام بتسجيل الدخول بكلمة مرور ربط حساب Google وتسجيل الدخول بأي من الطريقتين في المستقبل. أو ، يمكن لمستخدم مجهول ربط حساب Facebook ثم تسجيل الدخول لاحقًا باستخدام Facebook لمتابعة استخدام التطبيق الخاص بك.

قبل ان تبدأ

أضف دعمًا لاثنين أو أكثر من موفري المصادقة (ربما بما في ذلك المصادقة المجهولة) إلى تطبيقك.

لربط بيانات اعتماد موفر المصادقة بحساب مستخدم موجود:

  1. سجّل دخول المستخدم باستخدام أي موفر أو طريقة مصادقة.
  2. إكمال تسجيل الدخول تدفق لموفر المصادقة الجديد حتى، ولكن ليس بما في ذلك استدعاء أحد FIRAuth.signInWith الأساليب. على سبيل المثال ، احصل على رمز معرف Google الخاص بالمستخدم أو رمز الوصول إلى Facebook أو البريد الإلكتروني وكلمة المرور.
  3. الحصول على FIRAuthCredential لموفر المصادقة الجديد:

    جوجل تسجيل الدخول
    سويفت
    guard
      let authentication = user?.authentication,
      let idToken = authentication.idToken
    else {
      return
    }
    
    let credential = GoogleAuthProvider.credential(withIDToken: idToken,
                                                   accessToken: authentication.accessToken)
    
    ج موضوعية
    GIDAuthentication *authentication = user.authentication;
    FIRAuthCredential *credential =
    [FIRGoogleAuthProvider credentialWithIDToken:authentication.idToken
                                     accessToken:authentication.accessToken];
    
    تسجيل الدخول الى الفيسبوك
    سويفت
    let credential = FacebookAuthProvider
      .credential(withAccessToken: AccessToken.current!.tokenString)
    
    ج موضوعية
    FIRAuthCredential *credential = [FIRFacebookAuthProvider
        credentialWithAccessToken:[FBSDKAccessToken currentAccessToken].tokenString];
    
    تسجيل الدخول إلى البريد الإلكتروني وكلمة المرور
    سويفت
    let credential = EmailAuthProvider.credential(withEmail: email, password: password)
    
    ج موضوعية
    FIRAuthCredential *credential =
        [FIREmailAuthProvider credentialWithEmail:email
                                                 password:password];
    
  4. تمرير FIRAuthCredential الكائن إلى قعت في المستخدم linkWithCredential:completion: الأسلوب:

    سويفت
        user.link(with: credential) { authResult, error in
      // ...
    }
    }
    
    ج موضوعية
        [[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
                // ...
            }
    

    ج موضوعية

    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 نفسها.

يمكنك إلغاء ربط موفر المصادقة من حساب ، بحيث لا يمكن للمستخدم تسجيل الدخول باستخدام هذا الموفر.

لإلغاء ربط مزود المصادقة من حساب المستخدم، وتمرير ID مزود ل unlinkFromProvider:completion: الأسلوب. يمكنك الحصول على بطاقات هوية مقدم من مقدمي المصادقة مرتبطة مستخدم من providerData الممتلكات.

سويفت

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

ج موضوعية

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