شما میتوانید با پیوند دادن اعتبارنامههای ارائهدهندهی احراز هویت به یک حساب کاربری موجود، به کاربران اجازه دهید با استفاده از چندین ارائهدهندهی احراز هویت به برنامهی شما وارد شوند. کاربران صرف نظر از ارائهدهندهی احراز هویتی که برای ورود به سیستم استفاده کردهاند، با همان شناسهی کاربری Firebase قابل شناسایی هستند. به عنوان مثال، کاربری که با رمز عبور وارد سیستم شده است، میتواند یک حساب گوگل را پیوند دهد و در آینده با هر دو روش وارد سیستم شود. یا، یک کاربر ناشناس میتواند یک حساب فیسبوک را پیوند دهد و سپس، بعداً، برای ادامهی استفاده از برنامهی شما، با فیسبوک وارد سیستم شود.
قبل از اینکه شروع کنی
پشتیبانی از دو یا چند ارائهدهندهی احراز هویت (احتمالاً شامل احراز هویت ناشناس) را به برنامهی خود اضافه کنید.
اعتبارنامههای ارائهدهندهی احراز هویت را به یک حساب کاربری پیوند دهید
برای پیوند دادن اعتبارنامههای ارائهدهندهی احراز هویت به یک حساب کاربری موجود:
- کاربر را با استفاده از هر ارائه دهنده یا روش احراز هویتی وارد سیستم کنید.
- روند ورود به سیستم برای ارائهدهندهی احراز هویت جدید را تا فراخوانی یکی از متدهای
FIRAuth.signInWithتکمیل کنید، اما این کار را شامل نمیشود. برای مثال، توکن شناسهی گوگل کاربر، توکن دسترسی فیسبوک یا ایمیل و رمز عبور را دریافت کنید. یک
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];
شیء
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 دسترسی پیدا کند.
لغو ارتباط یک ارائهدهندهی احراز هویت از یک حساب کاربری
یک حساب کاربری Firebase میتواند چندین ارائهدهندهی احراز هویت (مثلاً ایمیل/رمز عبور، گوگل، فیسبوک) داشته باشد که به کاربر اجازه میدهد از طریق روشهای مختلف به یک حساب Firebase وارد شود.
اگر ارتباط یک ارائهدهندهی احراز هویت را با حساب کاربری قطع کنید، کاربر دیگر نمیتواند با آن ارائهدهنده وارد سیستم شود.
برای قطع ارتباط یک ارائهدهندهی احراز هویت از یک حساب کاربری، شناسهی ارائهدهنده را به متد unlink ارسال کنید. میتوانید شناسههای ارائهدهندهی ارائهدهندگان احراز هویت مرتبط با یک کاربر را از ویژگی providerData دریافت کنید.
سویفت
Auth.auth().currentUser?.unlink(fromProvider: providerID!) { user, error in // ... }
هدف-سی
[[FIRAuth auth].currentUser unlinkFromProvider:providerID completion:^(FIRUser *_Nullable user, NSError *_Nullable error) { // ... }];
عیبیابی
اگر هنگام تلاش برای پیوند دادن چندین حساب با خطا مواجه شدید، به مستندات مربوط به آدرسهای ایمیل تأیید شده مراجعه کنید.