通過將身份驗證提供程序憑據鏈接到現有用戶帳戶,可以允許用戶使用多個身份驗證提供程序登錄您的應用程序。無論使用哪種身份驗證提供程序登錄,都可以使用相同的Firebase用戶ID來識別用戶。例如,使用密碼登錄的用戶將來可以鏈接Google帳戶並使用這兩種方法登錄。或者,匿名用戶可以鏈接Facebook帳戶,然後再登錄Facebook以繼續使用您的應用程序。
在你開始之前
在您的應用中添加對兩個或多個身份驗證提供程序(可能包括匿名身份驗證)的支持。
將身份驗證提供者憑據鏈接到用戶帳戶
要將身份驗證提供程序憑據鏈接到現有用戶帳戶,請執行以下操作:
- 使用任何身份驗證提供程序或方法登錄用戶。
- 完成新身份驗證提供程序的登錄流程,但不包括調用
FIRAuth.signInWith
方法之一。例如,獲取用戶的Google ID令牌,Facebook訪問令牌或電子郵件和密碼。 獲取新身份驗證提供程序的
FIRAuthCredential
:Google登錄
迅速
guard let authentication = user.authentication else { return } let credential = GoogleAuthProvider.credential(withIDToken: authentication.idToken, accessToken: authentication.accessToken)
目標C
GIDAuthentication *authentication = user.authentication; FIRAuthCredential *credential = [FIRGoogleAuthProvider credentialWithIDToken:authentication.idToken accessToken:authentication.accessToken];
Facebook登入
迅速
let credential = FacebookAuthProvider.credential(withAccessToken: AccessToken.current!.tokenString)
物鏡
FIRAuthCredential *credential = [FIRFacebookAuthProvider credentialWithAccessToken:[FBSDKAccessToken currentAccessToken].tokenString];
電子郵件密碼登錄
迅速
let credential = EmailAuthProvider.credential(withEmail: email, password: password)
目標C
FIRAuthCredential *credential = [FIREmailAuthProvider credentialWithEmail:email password:password];
將
FIRAuthCredential
對FIRAuthCredential
傳遞給登錄用戶的linkWithCredential:completion:
方法:迅速
user.link(with: credential) { (authResult, error) in // ... } }
目標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 // ... }
目標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數據。
取消身份驗證提供者與用戶帳戶的鏈接
您可以取消與帳戶的身份驗證提供程序的鏈接,以使用戶無法再使用該提供程序登錄。
要將身份驗證提供程序與用戶帳戶解除鏈接,請將提供程序ID傳遞給unlinkFromProvider:completion:
方法。您可以從providerData
屬性獲取鏈接到用戶的身份驗證提供程序的提供程序ID。
迅速
Auth.auth().currentUser?.unlink(fromProvider: providerID!) { (user, error) in // ... }
目標C
[[FIRAuth auth].currentUser unlinkFromProvider:providerID completion:^(FIRUser *_Nullable user, NSError *_Nullable error) { // ... }];