Para permitir que los usuarios accedan a la app con varios proveedores de autenticación, puedes vincular las credenciales de estos proveedores con una cuenta de usuario existente. Los usuarios se pueden identificar con el mismo ID de usuario de Firebase, sin importar el proveedor de autenticación que hayan usado para acceder. Por ejemplo, un usuario que accedió con una contraseña puede vincular una Cuenta de Google y después usar cualquiera de los dos métodos para acceder. Por otra parte, un usuario anónimo puede vincular una cuenta de Facebook y luego acceder con Facebook para continuar usando la app.
Antes de comenzar
Agrega compatibilidad para dos o más proveedores de autenticación (posiblemente incluida la autenticación anónima) a la app.
Vincula las credenciales del proveedor de autenticación con una cuenta de usuario
Para vincular las credenciales del proveedor de autenticación con una cuenta de usuario existente:
- Permite que el usuario acceda mediante cualquier proveedor o método de autenticación.
- Completa el flujo de acceso del proveedor de autenticación nuevo, pero solamente hasta el paso anterior a llamar a uno de los métodos
FIRAuth.signInWith
. Por ejemplo, obtén el token de ID de Google, el token de acceso de Facebook o el correo electrónico y la contraseña del usuario. Obtén una
FIRAuthCredential
para el proveedor de autenticación nuevo:Acceso con 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];
Acceso con Facebook
Swift
let credential = FacebookAuthProvider .credential(withAccessToken: AccessToken.current!.tokenString)
Objective-C
FIRAuthCredential *credential = [FIRFacebookAuthProvider credentialWithAccessToken:[FBSDKAccessToken currentAccessToken].tokenString];
Acceso con correo electrónico y contraseña
Swift
let credential = EmailAuthProvider.credential(withEmail: email, password: password)
Objective-C
FIRAuthCredential *credential = [FIREmailAuthProvider credentialWithEmail:email password:password];
Pasa el objeto
FIRAuthCredential
al métodolinkWithCredential:completion:
del usuario que accedió:Swift
user.link(with: credential) { authResult, error in // ... } }
Objective-C
[[FIRAuth auth].currentUser linkWithCredential:credential completion:^(FIRAuthDataResult *result, NSError *_Nullable error) { // ... }];
La llamada a
linkWithCredential:completion:
fallará si ya se vincularon las credenciales con la cuenta de otro usuario. En esta situación, debes administrar la fusión de las cuentas y los datos asociados según corresponda para la app: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 // ... }];
Si la llamada a linkWithCredential:completion:
se hace correctamente, el usuario podrá acceder con cualquier proveedor de autenticación vinculado para usar los mismos datos en Firebase.
Desvincula un proveedor de autenticación de una cuenta de usuario
Puedes desvincular un proveedor de autenticación de una cuenta para que el usuario ya no pueda acceder con ese proveedor.
Para desvincular un proveedor de autenticación de una cuenta de usuario, pasa el ID del proveedor al método unlink
. Puedes obtener los ID de los proveedores de autenticación vinculados con un usuario desde la propiedad 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) { // ... }];