Vincular varios proveedores a una cuenta
En este documento, se muestra cómo vincular varios proveedores a una cuenta única de Identity Platform.
Identity Platform usa un ID único para identificar a los usuarios. Esto permite que los usuarios accedan a la misma cuenta con proveedores diferentes. Por ejemplo, un usuario que se registró inicialmente con un número de teléfono podría, luego, vincular su cuenta de Google y usar cualquiera de estos dos métodos para acceder.
Antes de comenzar
Agrega la compatibilidad con dos o más proveedores de identidad a tu app.
Habilita o inhabilita la vinculación de cuentas
La configuración de la vinculación de cuentas determina de qué forma Identity Platform maneja los usuarios que intentan acceder con el mismo correo electrónico mediante proveedores diferentes.
Vincula cuentas que usen el mismo correo electrónico: Identity Platform generará un error si un usuario intenta acceder con un correo electrónico que ya está en uso. Tu app puede detectar este error y vincular el proveedor nuevo con su cuenta existente.
Crea varias cuentas para cada proveedor de identidad: Se creará una cuenta de usuario nueva de Identity Platform cada vez que un usuario acceda con un proveedor diferente.
Para elegir una configuración, haz lo siguiente:
Ve a la página Configuración de Identity Platform en Google Cloud Console.
Selecciona una configuración en Vinculación de cuentas de usuario.
Haz clic en Guardar.
Vincula credenciales de proveedores federados
Para vincular credenciales de un proveedor federado, haz lo siguiente:
Permite que el usuario acceda mediante cualquier proveedor o método de autenticación.
Obtén el objeto del proveedor que corresponde al proveedor que deseas vincular con la cuenta del usuario. Por ejemplo:
Web versión 9
import { GoogleAuthProvider, FacebookAuthProvider, TwitterAuthProvider, GithubAuthProvider } from "firebase/auth"; const googleProvider = new GoogleAuthProvider(); const facebookProvider = new FacebookAuthProvider(); const twitterProvider = new TwitterAuthProvider(); const githubProvider = new GithubAuthProvider();
Versión web 8
var googleProvider = new firebase.auth.GoogleAuthProvider(); var facebookProvider = new firebase.auth.FacebookAuthProvider(); var twitterProvider = new firebase.auth.TwitterAuthProvider(); var githubProvider = new firebase.auth.GithubAuthProvider();
Pídele al usuario que acceda con el proveedor que deseas vincular. Puedes abrir una ventana emergente o redireccionar la página actual. El redireccionamiento es más sencillo para los usuarios de dispositivos móviles.
Para mostrar una ventana emergente, llama a
linkWithPopup()
:Web versión 9
import { getAuth, linkWithPopup, GoogleAuthProvider } from "firebase/auth"; const provider = new GoogleAuthProvider(); const auth = getAuth(); linkWithPopup(auth.currentUser, provider).then((result) => { // Accounts successfully linked. const credential = GoogleAuthProvider.credentialFromResult(result); const user = result.user; // ... }).catch((error) => { // Handle Errors here. // ... });
Versión web 8
auth.currentUser.linkWithPopup(provider).then((result) => { // Accounts successfully linked. var credential = result.credential; var user = result.user; // ... }).catch((error) => { // Handle Errors here. // ... });
Para redireccionar la página, primero llama a
linkWithRedirect()
:Sigue las prácticas recomendadas cuando uses
signInWithRedirect
,linkWithRedirect
oreauthenticateWithRedirect
.Web versión 9
import { getAuth, linkWithRedirect, GoogleAuthProvider } from "firebase/auth"; const provider = new GoogleAuthProvider(); const auth = getAuth(); linkWithRedirect(auth.currentUser, provider) .then(/* ... */) .catch(/* ... */);
Versión web 8
auth.currentUser.linkWithRedirect(provider) .then(/* ... */) .catch(/* ... */);
Una vez que el usuario acceda, se lo redireccionará de vuelta a tu app. Luego, puedes recuperar el resultado del acceso si llamas a
getRedirectResult()
:Web versión 9
import { getRedirectResult } from "firebase/auth"; getRedirectResult(auth).then((result) => { const credential = GoogleAuthProvider.credentialFromResult(result); if (credential) { // Accounts successfully linked. const user = result.user; // ... } }).catch((error) => { // Handle Errors here. // ... });
Versión web 8
auth.getRedirectResult().then((result) => { if (result.credential) { // Accounts successfully linked. var credential = result.credential; var user = result.user; // ... } }).catch((error) => { // Handle Errors here. // ... });
La cuenta del usuario con el proveedor federado ahora está vinculada con su cuenta de Identity Platform y puede usar el proveedor para acceder.
Vincula credenciales de correo electrónico y contraseña
Para agregar una dirección de correo electrónico y una contraseña a una cuenta de usuario existente, haz lo siguiente:
Permite que el usuario acceda mediante cualquier método o proveedor de identidad.
Pide al usuario que ingrese una dirección de correo electrónico y una contraseña.
Crea un objeto
AuthCredential
con la dirección de correo electrónico y la contraseña:Web versión 9
import { EmailAuthProvider } from "firebase/auth"; const credential = EmailAuthProvider.credential(email, password);
Versión web 8
var credential = firebase.auth.EmailAuthProvider.credential(email, password);
Pasa el objeto
AuthCredential
al métodolinkWithCredential()
en el usuario que accedió:Web versión 9
import { getAuth, linkWithCredential } from "firebase/auth"; const auth = getAuth(); linkWithCredential(auth.currentUser, credential) .then((usercred) => { const user = usercred.user; console.log("Account linking success", user); }).catch((error) => { console.log("Account linking error", error); });
Versión web 8
auth.currentUser.linkWithCredential(credential) .then((usercred) => { var user = usercred.user; console.log("Account linking success", user); }).catch((error) => { console.log("Account linking error", error); });
Las credenciales del correo electrónico y la contraseña ahora están vinculadas a la cuenta de Identity Platform del usuario y pueden usarlas para acceder.
Ten en cuenta que una credencial de proveedor federado se puede vincular a una cuenta de correo electrónico o contraseña con un correo electrónico diferente. Si esto sucede, se puede usar el correo electrónico correspondiente al proveedor federado para crear otra cuenta de correo electrónico o contraseña.
Maneja el error de account-exists-with-different-credential
Si habilitaste la configuración Vincular cuentas que usan el mismo correo electrónico en Google Cloud Console, cuando un usuario intenta acceder a un proveedor (como SAML) con un correo electrónico que ya existe para otro proveedor (como Google), se muestra el error auth/account-exists-with-different-credential
(junto con un objeto AuthCredential
).
Para solucionar este error, pídele al usuario que acceda con el proveedor existente.
Luego, llama a linkWithCredential()
, linkWithPopup()
o linkWithRedirect()
para asociar el proveedor nuevo con su cuenta mediante AuthCredential
.
En el siguiente ejemplo, se muestra cómo controlar este error cuando un usuario intenta acceder mediante Facebook:
JavaScript
// User tries to sign in with Facebook.
auth.signInWithPopup(new firebase.auth.FacebookAuthProvider()).catch(err => {
// User's email already exists.
if (err.code === 'auth/account-exists-with-different-credential') {
// The pending Facebook credential.
var pendingCred = err.credential;
// The provider account's email address.
var email = err.email;
// Get the sign-in methods for this email.
auth.fetchSignInMethodsForEmail(email).then(methods => {
// If the user has several sign-in methods, the first method
// in the list will be the "recommended" method to use.
if (methods[0] === 'password') {
// TODO: Ask the user for their password.
// In real scenario, you should handle this asynchronously.
var password = promptUserForPassword();
auth.signInWithEmailAndPassword(email, password).then(result => {
return result.user.linkWithCredential(pendingCred);
}).then(() => {
// Facebook account successfully linked to the existing user.
goToApp();
});
return;
}
// All other cases are external providers.
// Construct provider object for that provider.
// TODO: Implement getProviderForProviderId.
var provider = getProviderForProviderId(methods[0]);
// At this point, you should let the user know that they already have an
// account with a different provider, and validate they want to sign in
// with the new provider.
// Note: Browsers usually block popups triggered asynchronously, so in
// real app, you should ask the user to click on a "Continue" button
// that will trigger signInWithPopup().
auth.signInWithPopup(provider).then(result => {
// Note: Identity Platform doesn't control the provider's sign-in
// flow, so it's possible for the user to sign in with an account
// with a different email from the first one.
// Link the Facebook credential. We have access to the pending
// credential, so we can directly call the link method.
result.user.linkWithCredential(pendingCred).then(usercred => {
// Success.
goToApp();
});
});
});
}
});
El uso de un redireccionamiento es similar al uso de una ventana emergente, excepto que tendrás que almacenar en caché la credencial pendiente entre los redireccionamientos de la página (por ejemplo, mediante el uso del almacenamiento de sesión).
Ten en cuenta que algunos proveedores, como Google y Microsoft, funcionan como proveedores de identidad social y de correo electrónico. Los proveedores de correo electrónico se consideran como autorizados para todas las direcciones relacionadas con su dominio de correo electrónico alojado. Esto significa que un usuario que accede con una dirección de correo electrónico alojada por el mismo proveedor nunca generará este error (por ejemplo, si se accede con Google mediante un correo electrónico @gmail.com
o con Microsoft mediante un correo electrónico @live.com
o @outlook.com
).
Fusiona cuentas de forma manual
Si un usuario intenta acceder con credenciales que ya están vinculadas con otra cuenta de usuario mediante el mismo proveedor, fallarán los métodos integrados del SDK de cliente para la vinculación de cuentas. En esta situación, deberás fusionar las cuentas manualmente y, luego, borrar la segunda cuenta. Por ejemplo:
JavaScript
// Sign in first account.
const result1 = await auth.signInWithCredential(cred1);
const user1 = result1.user;
// Try to link a credential that belongs to an existing account
try {
await user1.linkWithCredential(cred2);
} catch (error) {
// cred2 already exists so an error is thrown.
const result2 = await auth.signInWithCredential(error.credential);
const user2 = result2.user;
// Merge the data.
mergeData(user1, user2);
// Delete one of the accounts, and try again.
await user2.delete();
// Linking now will work.
await user1.linkWithCredential(result2.credential);
}
Desvincula un proveedor
Puedes desvincular un proveedor de la cuenta de un usuario. El usuario ya no podrá autenticarse con ese proveedor.
Para desvincular un proveedor, 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
.
Web versión 9
import { getAuth, unlink } from "firebase/auth"; const auth = getAuth(); unlink(auth.currentUser, providerId).then(() => { // Auth provider unlinked from account // ... }).catch((error) => { // An error happened // ... });
Versión web 8
user.unlink(providerId).then(() => { // Auth provider unlinked from account // ... }).catch((error) => { // An error happened // ... });
¿Qué sigue?
- Agrega la compatibilidad con diferentes proveedores de identidad a tu app.
- Obtén información sobre cómo administrar proveedores de manera programática.