ربط موفري مصادقة متعددين بحساب على أنظمة Apple الأساسية

يمكنك السماح للمستخدمين بتسجيل الدخول إلى تطبيقك باستخدام موفري مصادقة متعددين عن طريق ربط بيانات اعتماد موفر المصادقة بحساب مستخدم حالي. يمكن التعرف على المستخدمين من خلال نفس معرف مستخدم 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)
    
    ج موضوعية
    FIRAuthCredential *credential =
    [FIRGoogleAuthProvider credentialWithIDToken:result.user.idToken.tokenString
                                     accessToken:result.user.accessToken.tokenString];
    
    تسجيل الدخول الى الفيسبوك
    سويفت
    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. قم linkWithCredential:completion: كائن FIRAuthCredential إلى رابط المستخدم المسجل الدخول:

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

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

لإلغاء ارتباط موفر المصادقة بحساب المستخدم ، مرر معرف الموفر إلى طريقة unlink . يمكنك الحصول على معرفات الموفر لموفري المصادقة المرتبطين بمستخدم من خاصية providerData .

سويفت

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

ج موضوعية

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