Puede permitir que los usuarios inicien sesión en su aplicación utilizando múltiples proveedores de autenticación vinculando las credenciales del proveedor de autenticación a una cuenta de usuario existente. Los usuarios son identificables por el mismo ID de usuario de Firebase independientemente del proveedor de autenticación que utilizaron para iniciar sesión. Por ejemplo, un usuario que inició sesión con una contraseña puede vincular una cuenta de Google e iniciar sesión con cualquiera de los métodos en el futuro. O bien, un usuario anónimo puede vincular una cuenta de Facebook y luego, iniciar sesión en Facebook para continuar usando su aplicación.
Antes de que empieces
Agregue soporte para dos o más proveedores de autenticación (posiblemente incluida la autenticación anónima) a su aplicación.
Vincular las credenciales del proveedor de autenticación a una cuenta de usuario
Para vincular las credenciales del proveedor de autenticación a una cuenta de usuario existente:
- Inicie sesión como usuario utilizando cualquier proveedor o método de autenticación.
- Complete el flujo de inicio de sesión para el nuevo proveedor de autenticación hasta, pero sin incluir, llamar a uno de los métodos
FIRAuth.signInWith
. Por ejemplo, obtenga el token de identificación de Google del usuario, el token de acceso de Facebook o el correo electrónico y la contraseña. Obtenga una
FIRAuthCredential
para el nuevo proveedor de autenticación:Iniciar sesión en Google
Rápido
guard let authentication = user?.authentication, let idToken = authentication.idToken else { return } let credential = GoogleAuthProvider.credential(withIDToken: idToken, accessToken: authentication.accessToken)
C objetivo
FIRAuthCredential *credential = [FIRGoogleAuthProvider credentialWithIDToken:result.user.idToken.tokenString accessToken:result.user.accessToken.tokenString];
Iniciar sesión en Facebook
Rápido
let credential = FacebookAuthProvider .credential(withAccessToken: AccessToken.current!.tokenString)
C objetivo
FIRAuthCredential *credential = [FIRFacebookAuthProvider credentialWithAccessToken:[FBSDKAccessToken currentAccessToken].tokenString];
Inicio de sesión con contraseña de correo electrónico
Rápido
let credential = EmailAuthProvider.credential(withEmail: email, password: password)
C objetivo
FIRAuthCredential *credential = [FIREmailAuthProvider credentialWithEmail:email password:password];
Pase el objeto
FIRAuthCredential
al métodolinkWithCredential:completion:
del usuario que inició sesión:Rápido
user.link(with: credential) { authResult, error in // ... } }
C objetivo
[[FIRAuth auth].currentUser linkWithCredential:credential completion:^(FIRAuthDataResult *result, NSError *_Nullable error) { // ... }];
La llamada a
linkWithCredential:completion:
fallará si las credenciales ya están vinculadas a otra cuenta de usuario. En esta situación, debe gestionar la combinación de las cuentas y los datos asociados según corresponda para su aplicación:Rápido
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 objetivo
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 // ... }];
Si la llamada a linkWithCredential:completion:
tiene éxito, el usuario ahora puede iniciar sesión con cualquier proveedor de autenticación vinculado y acceder a los mismos datos de Firebase.
Desvincular un proveedor de autenticación de una cuenta de usuario
Puede desvincular un proveedor de autenticación de una cuenta, de modo que el usuario ya no pueda iniciar sesión con ese proveedor.
Para desvincular un proveedor de autenticación de una cuenta de usuario, pase el ID del proveedor al método unlink
. Puede obtener los ID de los proveedores de autenticación vinculados a un usuario desde la propiedad providerData
.
Rápido
Auth.auth().currentUser?.unlink(fromProvider: providerID!) { user, error in // ... }
C objetivo
[[FIRAuth auth].currentUser unlinkFromProvider:providerID completion:^(FIRUser *_Nullable user, NSError *_Nullable error) { // ... }];