Bạn có thể cho phép người dùng đăng nhập vào ứng dụng của mình bằng nhiều phương thức xác thực bằng cách liên kết thông tin đăng nhập của nhà cung cấp dịch vụ xác thực với một tài khoản người dùng hiện có. Người dùng có thể được nhận dạng bởi cùng một mã nhận dạng người dùng Firebase bất kể nhà cung cấp dịch vụ xác thực mà họ đã sử dụng để đăng nhập. Ví dụ: một người dùng đã đăng nhập có thể liên kết Tài khoản Google và đăng nhập bằng một trong hai phương thức trong tương lai. Hoặc người dùng ẩn danh có thể liên kết tài khoản Facebook và sau đó ký đăng nhập với Facebook để tiếp tục sử dụng ứng dụng của bạn.
Trước khi bắt đầu
Thêm tính năng hỗ trợ cho 2 hoặc nhiều nhà cung cấp dịch vụ xác thực (có thể bao gồm xác thực ẩn danh) cho ứng dụng của mình.
Liên kết thông tin đăng nhập của nhà cung cấp dịch vụ xác thực với tài khoản người dùng
Cách liên kết thông tin đăng nhập của nhà cung cấp dịch vụ xác thực với một tài khoản người dùng hiện có:
- Đăng nhập người dùng bằng bất kỳ phương thức hoặc nhà cung cấp dịch vụ xác thực nào.
- Hoàn tất quy trình đăng nhập cho nhà cung cấp dịch vụ xác thực mới tối đa, nhưng không
bao gồm cả việc gọi một trong các phương thức
FIRAuth.signInWith
. Ví dụ: nhận mã thông báo ID Google, mã truy cập Facebook hoặc email và mật khẩu của người dùng. Nhận
FIRAuthCredential
cho nhà cung cấp dịch vụ xác thực mới:Đăng nhập bằng tài khoản 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];
Đăng nhập Facebook
Swift
let credential = FacebookAuthProvider .credential(withAccessToken: AccessToken.current!.tokenString)
Objective-C
FIRAuthCredential *credential = [FIRFacebookAuthProvider credentialWithAccessToken:[FBSDKAccessToken currentAccessToken].tokenString];
Đăng nhập bằng email bằng mật khẩu
Swift
let credential = EmailAuthProvider.credential(withEmail: email, password: password)
Objective-C
FIRAuthCredential *credential = [FIREmailAuthProvider credentialWithEmail:email password:password];
Truyền đối tượng
FIRAuthCredential
đến tài khoản của người dùng đã đăng nhập Phương thứclinkWithCredential:completion:
:Swift
user.link(with: credential) { authResult, error in // ... } }
Objective-C
[[FIRAuth auth].currentUser linkWithCredential:credential completion:^(FIRAuthDataResult *result, NSError *_Nullable error) { // ... }];
Lệnh gọi đến
linkWithCredential:completion:
sẽ không thực hiện được nếu thông tin đăng nhập là đã được liên kết với một tài khoản người dùng khác. Trong tình huống này, bạn phải xử lý hợp nhất các tài khoản và dữ liệu liên quan sao cho phù hợp với ứng dụng của bạn: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 // ... }];
Nếu lệnh gọi đến linkWithCredential:completion:
thành công thì giờ đây, người dùng có thể đăng nhập bằng
bất kỳ nhà cung cấp dịch vụ xác thực nào được liên kết và truy cập vào cùng một dữ liệu Firebase.
Huỷ liên kết nhà cung cấp dịch vụ xác thực khỏi tài khoản người dùng
Bạn có thể huỷ liên kết nhà cung cấp dịch vụ xác thực khỏi một tài khoản để người dùng không thể đăng nhập bằng tài khoản nhà cung cấp đó lâu hơn.
Để huỷ liên kết nhà cung cấp dịch vụ xác thực khỏi tài khoản người dùng, hãy chuyển mã nhà cung cấp vào phương thức
unlink
. Bạn có thể lấy mã nhà cung cấp
trong số các nhà cung cấp dịch vụ xác thực được liên kết với người dùng từ providerData
thuộc tính này.
Swift
Auth.auth().currentUser?.unlink(fromProvider: providerID!) { user, error in // ... }
Objective-C
[[FIRAuth auth].currentUser unlinkFromProvider:providerID completion:^(FIRUser *_Nullable user, NSError *_Nullable error) { // ... }];