ربط عدة مقدّمي خدمات مصادقة بحساب على منصات Apple

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

قبل البدء

أضِف إمكانية استخدام اثنين أو أكثر من مقدّمي خدمات المصادقة (بما في ذلك المصادقة بدون تحديد الهوية) إلى تطبيقك.

لربط بيانات اعتماد مقدّم خدمة المصادقة بحساب مستخدم حالي، اتّبِع الخطوات التالية:

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

    تسجيل الدخول بحساب Google
    Swift
    guard   let authentication = user?.authentication,   let idToken = authentication.idToken else {   return }  let credential = GoogleAuthProvider.credential(withIDToken: idToken,                                                accessToken: authentication.accessToken)
    Objective-C
    FIRAuthCredential *credential = [FIRGoogleAuthProvider credentialWithIDToken:result.user.idToken.tokenString                                  accessToken:result.user.accessToken.tokenString];
    تسجيل الدخول عبر Facebook
    Swift
    let credential = FacebookAuthProvider   .credential(withAccessToken: AccessToken.current!.tokenString)
    Objective-C
    FIRAuthCredential *credential = [FIRFacebookAuthProvider     credentialWithAccessToken:[FBSDKAccessToken currentAccessToken].tokenString];
    تسجيل الدخول باستخدام عنوان البريد الإلكتروني وكلمة المرور
    Swift
    let credential = EmailAuthProvider.credential(withEmail: email, password: password)
    Objective-C
    FIRAuthCredential *credential =     [FIREmailAuthProvider credentialWithEmail:email                                              password:password];
  4. مرِّر العنصر FIRAuthCredential إلى الطريقة linkWithCredential:completion: الخاصة بالمستخدم الذي سجّل الدخول:

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

    سيتعذّر إجراء طلب إلى linkWithCredential:completion: إذا كانت بيانات الاعتماد مرتبطة مسبقًا بحساب مستخدم آخر. في هذه الحالة، عليك التعامل مع دمج الحسابات والبيانات المرتبطة بها على النحو المناسب لتطبيقك:

    Swift

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

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

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

Swift

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

Objective-C

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

تحديد المشاكل وحلّها

إذا واجهت أخطاء عند محاولة ربط حسابات متعدّدة، راجِع المستندات حول عناوين البريد الإلكتروني التي تم إثبات ملكيتها.