Como vincular vários provedores a uma conta
Neste documento, você verá como vincular vários provedores a uma única conta do Identity Platform.
O Identity Platform usa um ID exclusivo para identificar usuários. Isso permite que os usuários façam login na mesma conta com provedores diferentes. Por exemplo, um usuário que inicialmente se registra com um número de telefone pode vincular a Conta do Google dele posteriormente e usar um dos métodos para fazer login.
Antes de começar
Adicione ao app o suporte para dois ou mais provedores de identidade.
Como ativar ou desativar a vinculação de contas
A configuração da vinculação de conta determina como o Identity Platform lida com os usuários que tentam fazer login com o mesmo e-mail usando diferentes provedores.
Contas vinculadas que usam o mesmo e-mail: o Identity Platform gerará um erro caso um usuário tente fazer login com um e-mail que já esteja em uso. O app pode identificar esse erro e vincular o novo provedor à conta atual.
Criar várias contas para cada provedor de identidade: uma nova conta de usuário do Identity Platform será criada sempre que um usuário fizer login com um provedor diferente.
Para escolher uma configuração:
Acesse a página Configurações do Identity Platform no console do Google Cloud.
Selecione uma configuração em Vinculação da conta do usuário.
Clique em Save.
Como vincular credenciais de provedores federados
Para vincular credenciais de um provedor federado:
Faça login do usuário com um provedor ou método de autenticação.
Consiga o objeto do provedor que corresponde ao provedor que você quer vincular à conta do usuário. Exemplo:
Versão 9 para a Web
import { GoogleAuthProvider, FacebookAuthProvider, TwitterAuthProvider, GithubAuthProvider } from "firebase/auth"; const googleProvider = new GoogleAuthProvider(); const facebookProvider = new FacebookAuthProvider(); const twitterProvider = new TwitterAuthProvider(); const githubProvider = new GithubAuthProvider();
Versão 8 para a Web
var googleProvider = new firebase.auth.GoogleAuthProvider(); var facebookProvider = new firebase.auth.FacebookAuthProvider(); var twitterProvider = new firebase.auth.TwitterAuthProvider(); var githubProvider = new firebase.auth.GithubAuthProvider();
Solicite que o usuário faça login com o provedor que você quer vincular. Você pode abrir uma janela pop-up ou redirecionar a página atual. O redirecionamento é mais fácil para usuários de dispositivos móveis.
Para mostrar um pop-up, chame
linkWithPopup()
:Versão 9 para a Web
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. // ... });
Versão 8 para a Web
auth.currentUser.linkWithPopup(provider).then((result) => { // Accounts successfully linked. var credential = result.credential; var user = result.user; // ... }).catch((error) => { // Handle Errors here. // ... });
Para redirecionar a página, primeiro chame
linkWithRedirect()
:Siga as práticas recomendadas ao usar
signInWithRedirect
,linkWithRedirect
oureauthenticateWithRedirect
.Versão 9 para a Web
import { getAuth, linkWithRedirect, GoogleAuthProvider } from "firebase/auth"; const provider = new GoogleAuthProvider(); const auth = getAuth(); linkWithRedirect(auth.currentUser, provider) .then(/* ... */) .catch(/* ... */);
Versão 8 para a Web
auth.currentUser.linkWithRedirect(provider) .then(/* ... */) .catch(/* ... */);
Depois que o usuário fizer login, ele será redirecionado ao seu app. Em seguida, recupere o resultado do login chamando
getRedirectResult()
:Versão 9 para a Web
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. // ... });
Versão 8 para a Web
auth.getRedirectResult().then((result) => { if (result.credential) { // Accounts successfully linked. var credential = result.credential; var user = result.user; // ... } }).catch((error) => { // Handle Errors here. // ... });
A conta do usuário com o provedor federado agora está vinculada à conta do Identity Platform e o provedor pode ser usado para fazer login.
Como vincular credenciais de e-mail e senha
Para adicionar um endereço de e-mail e uma senha a uma conta de usuário atual:
Faça login do usuário com um provedor ou método de identidade.
Solicite ao usuário um endereço de e-mail e uma senha.
Crie um objeto
AuthCredential
com o endereço de e-mail e a senha:Versão 9 para a Web
import { EmailAuthProvider } from "firebase/auth"; const credential = EmailAuthProvider.credential(email, password);
Versão 8 para a Web
var credential = firebase.auth.EmailAuthProvider.credential(email, password);
Transmita o objeto
AuthCredential
para o métodolinkWithCredential()
no usuário conectado:Versão 9 para a Web
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); });
Versão 8 para a Web
auth.currentUser.linkWithCredential(credential) .then((usercred) => { var user = usercred.user; console.log("Account linking success", user); }).catch((error) => { console.log("Account linking error", error); });
As credenciais de e-mail e senha agora estão vinculadas à conta do Identity Platform do usuário e podem usá-las para fazer login.
Uma credencial de provedor federado pode ser vinculada a uma conta de e-mail/senha com um e-mail diferente. Se isso acontecer, o e-mail correspondente ao provedor federado poderá ser usado para criar uma conta de e-mail/senha separada.
Como processar o erro account-exists-with-different-credential
Se você ativou a configuração Vincular contas que usam o mesmo e-mail no
console do Google Cloud, quando um usuário tentar fazer login em um provedor,
como o SAML, com um e-mail que já existe para outro provedor, como
o Google, o erro auth/account-exists-with-different-credential
é acionado
(junto com um objeto AuthCredential
).
Para lidar com esse erro, solicite que o usuário faça login com o provedor atual.
Em seguida, chame linkWithCredential()
, linkWithPopup()
ou
linkWithRedirect()
para associar o novo provedor à conta dele usando o AuthCredential
.
O exemplo a seguir mostra como tratar esse erro quando um usuário tenta fazer login usando o Facebook:
Versão 9 para a Web
import { signInWithPopup, signInWithEmailAndPassword, linkWithCredential } from "firebase/auth"; // User tries to sign in with Facebook. signInWithPopup(auth, facebookProvider).catch((error) => { // User's email already exists. if (error.code === 'auth/account-exists-with-different-credential') { // The pending Facebook credential. const pendingCred = error.credential; // The provider account's email address. const email = error.customData.email; // Present the user with a list of providers they might have // used to create the original account. // Then, ask the user to sign in with the existing provider. const method = promptUserForSignInMethod(); if (method === 'password') { // TODO: Ask the user for their password. // In real scenario, you should handle this asynchronously. const password = promptUserForPassword(); signInWithEmailAndPassword(auth, email, password).then((result) => { return linkWithCredential(result.user, 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. const provider = getProviderForProviderId(method); // 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(). signInWithPopup(auth, 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. linkWithCredential(result.user, pendingCred).then((userCred) => { // Success. goToApp(); }); }); } });
Versão 8 para a Web
// User tries to sign in with Facebook. auth.signInWithPopup(facebookProvider).catch((error) => { // User's email already exists. if (error.code === 'auth/account-exists-with-different-credential') { // The pending Facebook credential. const pendingCred = error.credential; // The provider account's email address. const email = error.email; // Present the user with a list of providers they might have // used to create the original account. // Then, ask the user to sign in with the existing provider. const method = promptUserForSignInMethod(); if (method === 'password') { // TODO: Ask the user for their password. // In real scenario, you should handle this asynchronously. const 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. const provider = getProviderForProviderId(method); // 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(); }); }); } });
O uso de um redirecionamento é semelhante a um pop-up, mas você precisa armazenar em cache a credencial pendente entre redirecionamentos de página (por exemplo, usando o armazenamento de sessão).
Alguns provedores, como o Google e a Microsoft, servem como provedores de e-mail e
identidades sociais. Os provedores de e-mail são considerados autoritativos para todos
os endereços relacionados ao domínio de e-mail hospedado. Isso significa que um usuário que fizer login
com um endereço de e-mail hospedado pelo mesmo provedor nunca gerará esse erro
(por exemplo, fazer login com o Google usando um @gmail.com
e-mail ou Microsoft
usando um @live.com
, @outlook.com
e-mail).
Como mesclar contas manualmente
Se um usuário tentar fazer login com credenciais que já estão vinculadas a outra conta de usuário usando o mesmo provedor, os métodos integrados do SDK do cliente para vinculação de contas vão falhar. Nessa situação, você precisará mesclar as contas manualmente e excluir a segunda conta. Exemplo:
Versão 9 para a Web
// Sign in first account.
const result1 = await signInWithCredential(auth, cred1);
const user1 = result1.user;
// Try to link a credential that belongs to an existing account
try {
await linkWithCredential(user1, cred2);
} catch (error) {
// cred2 already exists so an error is thrown.
const result2 = await signInWithCredential(auth, 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 linkWithCredential(user1, result2.credential);
}
Versão 8 para a Web
// 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);
}
Como desvincular um provedor
É possível desvincular um provedor da conta de um usuário. O usuário não poderá mais se autenticar com esse provedor.
Para desvincular um provedor, transmita o ID dele ao método unlink()
.
Você pode receber os IDs dos provedores de autenticação vinculados a um usuário usando a propriedade providerData
.
Versão 9 para a Web
import { getAuth, unlink } from "firebase/auth"; const auth = getAuth(); unlink(auth.currentUser, providerId).then(() => { // Auth provider unlinked from account // ... }).catch((error) => { // An error happened // ... });
Versão 8 para a Web
user.unlink(providerId).then(() => { // Auth provider unlinked from account // ... }).catch((error) => { // An error happened // ... });
A seguir
- Adicione compatibilidade com diferentes provedores de identidade ao seu app.
- Saiba como gerenciar provedores de modo programático.