Use o Firebase Authentication para fazer o login de um usuário por um link enviado a ele por e-mail. Nesse processo, o endereço de e-mail do usuário também é verificado.
O login por e-mail tem inúmeros benefícios:
- Inscrição e login simplificados.
- Menos chances de reutilizar senhas entre os aplicativos, o que pode diminuir a segurança até mesmo das senhas mais fortes.
- Capacidade de autenticar o usuário e verificar se ele é o legítimo proprietário do endereço de e-mail.
- O usuário só precisa de uma conta de e-mail acessível para fazer login. Não são necessários números de telefone nem contas em redes sociais.
- O usuário faz login com segurança sem precisar fornecer ou lembrar de uma senha. Em dispositivos móveis, isso é bem importante porque facilita a vida do usuário.
- O usuário que já tiver feito login com um identificador de e-mail (senha ou federado) poderá se conectar depois apenas com o e-mail. Por exemplo, se ele se esquecer da senha, ainda será possível fazer login sem precisar redefini-la.
Antes de começar
Copie o snippet de inicialização do Console do Firebase para o projeto, conforme descrito na página Adicionar o Firebase a seu projeto do JavaScript, se ainda não tiver feito isso.
Ativar o login por link de e-mail no projeto do Firebase
Para que os usuários façam login usando um link enviado por e-mail, primeiro ative o provedor de e-mail e o método de login por link no projeto do Firebase:
- No console do Firebase, abra a seção Auth.
- Na guia Método de login, ative o provedor de E-mail/senha. Ative esse método para poder usar o login por link de e-mail.
- Na mesma seção, ative o método Link do e-mail (login sem senha).
- Clique em Salvar.
Enviar um link de autenticação ao endereço de e-mail do usuário
Para iniciar o fluxo de autenticação, apresente ao usuário uma interface que solicite que ele forneça seu endereço de e-mail e, em seguida, chame sendSignInLinkToEmail para solicitar que o Firebase envie o link de autenticação para o e-mail do usuário.
Crie o objeto
ActionCodeSettings, que fornece ao Firebase instruções sobre como criar o link de e-mail. Defina os seguintes campos:url: o link direto para incorporar e qualquer estado adicional a ser transmitido. É preciso que o domínio do link esteja adicionado na lista de domínios autorizados do Console do Firebase, encontrada na guia "Método de login" (Autenticação -> Configurações).
androideios: ajudam o Firebase Authentication a determinar se ele precisa criar um link somente para Web ou para dispositivos móveis que seja aberto em um dispositivo Android ou Apple.handleCodeInApp: definido como verdadeiro. É necessário sempre concluir o processo de login no app, ao contrário de outras ações fora de banda, como redefinição de senha e verificação de e-mail. Isso acontece porque o usuário precisa estar conectado e com o estado Auth mantido no app ao final do fluxo.linkDomain: quando domínios de link Hosting personalizados são definidos para um projeto, especifique qual deles usar quando o link for aberto por um app para dispositivos móveis especificado. Caso contrário, o domínio padrão será selecionado automaticamente (por exemplo, ).PROJECT_ID.firebaseapp.comdynamicLinkDomain: Descontinuado. Não especifique esse parâmetro.Web
const actionCodeSettings = { // URL you want to redirect back to. The domain (www.example.com) for this // URL must be in the authorized domains list in the Firebase Console. url: 'https://www.example.com/finishSignUp?cartId=1234', // This must be true. handleCodeInApp: true, iOS: { bundleId: 'com.example.ios' }, android: { packageName: 'com.example.android', installApp: true, minimumVersion: '12' }, // The domain must be configured in Firebase Hosting and owned by the project. linkDomain: 'custom-domain.com' };
Web
var actionCodeSettings = { // URL you want to redirect back to. The domain (www.example.com) for this // URL must be in the authorized domains list in the Firebase Console. url: 'https://www.example.com/finishSignUp?cartId=1234', // This must be true. handleCodeInApp: true, iOS: { bundleId: 'com.example.ios' }, android: { packageName: 'com.example.android', installApp: true, minimumVersion: '12' }, dynamicLinkDomain: 'example.page.link' };
Para saber mais sobre o
ActionCodeSettingsconsulte a seção Como transmitir o estado nas ações de e-mail.Solicite o e-mail ao usuário.
Envie o link de autenticação a esse endereço e salve o e-mail caso o usuário conclua o login no mesmo dispositivo.
Web
import { getAuth, sendSignInLinkToEmail } from "firebase/auth"; const auth = getAuth(); sendSignInLinkToEmail(auth, email, actionCodeSettings) .then(() => { // The link was successfully sent. Inform the user. // Save the email locally so you don't need to ask the user for it again // if they open the link on the same device. window.localStorage.setItem('emailForSignIn', email); // ... }) .catch((error) => { const errorCode = error.code; const errorMessage = error.message; // ... });
Web
firebase.auth().sendSignInLinkToEmail(email, actionCodeSettings) .then(() => { // The link was successfully sent. Inform the user. // Save the email locally so you don't need to ask the user for it again // if they open the link on the same device. window.localStorage.setItem('emailForSignIn', email); // ... }) .catch((error) => { var errorCode = error.code; var errorMessage = error.message; // ... });
Concluir o login com o link do e-mail
Preocupações com segurança
No Firebase Auth, o usuário precisa fornecer o endereço de e-mail ao concluir o fluxo de login. Isso evita que o link seja usado para fazer o login de um usuário indesejado ou em um dispositivo não intencional. Para fazer login, esse endereço precisa ser igual ao e-mail que recebeu o link.
É possível simplificar o fluxo dos usuários que abrem o link no mesmo dispositivo usado para solicitá-lo. Basta armazenar o endereço deles localmente quando enviar o e-mail de login. Por exemplo, você pode usar o localStorage ou cookies. Depois, utilize o endereço para concluir o fluxo. Não transmita o e-mail do usuário nos parâmetros de URL de redirecionamento e nem o reutilize, já que isso pode ativar injeções de sessão.
Após a conclusão do login, qualquer mecanismo anterior de login não verificado será removido do usuário, e todas as sessões atuais serão invalidadas. Por exemplo, se alguém tiver criado uma conta não verificada com a mesma senha e e-mail, a senha do usuário será removida. Isso impede que a pessoa que reivindicou a propriedade e criou essa conta faça login novamente com o e-mail e senha não confirmados.
Além disso, não deixe de usar um URL HTTPS na produção para impedir que o link possa ser interceptado por servidores intermediários.
Como concluir o login em uma página da Web
O formato do link direto do e-mail é igual ao
usado em ações fora de banda,
como verificação de e-mail, redefinição de senha e revogação de alterações.
No Firebase Auth, essa verificação é simplificada pelo fornecimento da API isSignInWithEmailLink que confere se o link é para login por e-mail.
Para concluir o login em uma página de destino, chame signInWithEmailLink com o e-mail do usuário e o link real que contém o código de uso único.
Web
import { getAuth, isSignInWithEmailLink, signInWithEmailLink } from "firebase/auth"; // Confirm the link is a sign-in with email link. const auth = getAuth(); if (isSignInWithEmailLink(auth, window.location.href)) { // Additional state parameters can also be passed via URL. // This can be used to continue the user's intended action before triggering // the sign-in operation. // Get the email if available. This should be available if the user completes // the flow on the same device where they started it. let email = window.localStorage.getItem('emailForSignIn'); if (!email) { // User opened the link on a different device. To prevent session fixation // attacks, ask the user to provide the associated email again. For example: email = window.prompt('Please provide your email for confirmation'); } // The client SDK will parse the code from the link for you. signInWithEmailLink(auth, email, window.location.href) .then((result) => { // Clear email from storage. window.localStorage.removeItem('emailForSignIn'); // You can access the new user by importing getAdditionalUserInfo // and calling it with result: // getAdditionalUserInfo(result) // You can access the user's profile via: // getAdditionalUserInfo(result)?.profile // You can check if the user is new or existing: // getAdditionalUserInfo(result)?.isNewUser }) .catch((error) => { // Some error occurred, you can inspect the code: error.code // Common errors could be invalid email and invalid or expired OTPs. }); }
Web
// Confirm the link is a sign-in with email link. if (firebase.auth().isSignInWithEmailLink(window.location.href)) { // Additional state parameters can also be passed via URL. // This can be used to continue the user's intended action before triggering // the sign-in operation. // Get the email if available. This should be available if the user completes // the flow on the same device where they started it. var email = window.localStorage.getItem('emailForSignIn'); if (!email) { // User opened the link on a different device. To prevent session fixation // attacks, ask the user to provide the associated email again. For example: email = window.prompt('Please provide your email for confirmation'); } // The client SDK will parse the code from the link for you. firebase.auth().signInWithEmailLink(email, window.location.href) .then((result) => { // Clear email from storage. window.localStorage.removeItem('emailForSignIn'); // You can access the new user via result.user // Additional user info profile not available via: // result.additionalUserInfo.profile == null // You can check if the user is new or existing: // result.additionalUserInfo.isNewUser }) .catch((error) => { // Some error occurred, you can inspect the code: error.code // Common errors could be invalid email and invalid or expired OTPs. }); }
Como concluir o login em um app para dispositivos móveis
O Firebase Authentication usa Firebase Hosting para enviar o link por e-mail a um dispositivo móvel. No aplicativo para dispositivos móveis, ele precisa estar configurado para detectar o link de entrada, analisar o link direto subjacente e então concluir o login conforme feito no fluxo da Web.
Para saber mais sobre como processar o login com o link por e-mail em um app Android, consulte este guia.
Para saber mais sobre como processar o login com o link por e-mail em um app da Apple, consulte o guia de plataformas da Apple.
Como vincular/reautenticar com link por e-mail
Também é possível vincular este método de autenticação a um usuário atual. Por exemplo, um usuário já autenticado com outro provedor, como número de telefone, pode incluir este método de login na conta dele.
A diferença está na segunda metade da operação:
Web
import { getAuth, linkWithCredential, EmailAuthProvider } from "firebase/auth"; // Construct the email link credential from the current URL. const credential = EmailAuthProvider.credentialWithLink( email, window.location.href); // Link the credential to the current user. const auth = getAuth(); linkWithCredential(auth.currentUser, credential) .then((usercred) => { // The provider is now successfully linked. // The phone user can now sign in with their phone number or email. }) .catch((error) => { // Some error occurred. });
Web
// Construct the email link credential from the current URL. var credential = firebase.auth.EmailAuthProvider.credentialWithLink( email, window.location.href); // Link the credential to the current user. firebase.auth().currentUser.linkWithCredential(credential) .then((usercred) => { // The provider is now successfully linked. // The phone user can now sign in with their phone number or email. }) .catch((error) => { // Some error occurred. });
Também é possível usá-lo para reautenticar um usuário de link por e-mail antes de executar uma operação confidencial.
Web
import { getAuth, reauthenticateWithCredential, EmailAuthProvider } from "firebase/auth"; // Construct the email link credential from the current URL. const credential = EmailAuthProvider.credentialWithLink( email, window.location.href); // Re-authenticate the user with this credential. const auth = getAuth(); reauthenticateWithCredential(auth.currentUser, credential) .then((usercred) => { // The user is now successfully re-authenticated and can execute sensitive // operations. }) .catch((error) => { // Some error occurred. });
Web
// Construct the email link credential from the current URL. var credential = firebase.auth.EmailAuthProvider.credentialWithLink( email, window.location.href); // Re-authenticate the user with this credential. firebase.auth().currentUser.reauthenticateWithCredential(credential) .then((usercred) => { // The user is now successfully re-authenticated and can execute sensitive // operations. }) .catch((error) => { // Some error occurred. });
No entanto, este fluxo pode não ser concluído, já que ele pode terminar em um dispositivo diferente do que o usado para fazer login. Nesse caso, é possível exibir um erro ao usuário para obrigá-lo a abrir o link no mesmo dispositivo. Você pode transmitir um estado no link para fornecer informações sobre o tipo de operação e o UID do usuário.
Descontinuado: como diferenciar e-mail/senha de link por e-mail
Se você criou o projeto em 15 de setembro de 2023 ou depois, a proteção contra enumeração de e-mails
está ativada por padrão. Esse recurso aumenta a segurança
das contas de usuário do projeto, mas desativa o método fetchSignInMethodsForEmail(), que anteriormente recomendamos para implementar fluxos que priorizam identificadores.
Embora você possa desativar a proteção contra enumeração de e-mails para o seu projeto, nós não recomendamos fazer isso.
Consulte a documentação sobre a proteção contra enumeração de e-mails para mais detalhes.
Modelo de e-mail padrão para login com link
O modelo de e-mail padrão inclui um carimbo de data/hora no assunto e no corpo do e-mail para que os e-mails subsequentes não sejam compactados em uma única conversa, com o link oculto.
Este modelo se aplica aos seguintes idiomas:
| Código | Idioma |
|---|---|
| ar | Árabe |
| zh-CN | Chinês (simplificado) |
| zh-TW | Chinês (tradicional) |
| nl | Holandês |
| en | Inglês |
| en-GB | Inglês (Reino Unido) |
| fr | Francês |
| de | Alemão |
| ID | Indonésio |
| it | Italiano |
| ja | Japonês |
| ko | Coreano |
| pl | Polonês |
| pt-BR | Português (Brasil) |
| pt-PT | Português (Portugal) |
| ru | Russo |
| es | Espanhol |
| es-419 | Espanhol (América Latina) |
| th | Tailandês |
Próximas etapas
Depois que um usuário faz login pela primeira vez, uma nova conta de usuário é criada e vinculada às credenciais, que podem ser o número do telefone, o nome de usuário e a senha ou as informações do provedor de autenticação. Essa nova conta é armazenada como parte do projeto do Firebase e pode ser usada para identificar um usuário em todos os apps do projeto, seja qual for o método de login utilizado.
-
Nos apps, a maneira recomendada de saber o status de autenticação do seu usuário é definindo um observador no objeto
Auth. É possível, então, receber as informações básicas de perfil do usuário do objetoUser. Consulte Gerenciar usuários. Nas Regras de segurança Firebase Realtime Database e Cloud Storage, você pode acessar o ID exclusivo do usuário conectado pela variável
authe usar essas informações para controlar quais dados um usuário pode acessar.
Os usuários podem fazer login no app usando vários provedores de autenticação. Basta vincular as credenciais desses provedores a uma conta de usuário.
Para desconectar um usuário, chame
signOut:
Web
import { getAuth, signOut } from "firebase/auth"; const auth = getAuth(); signOut(auth).then(() => { // Sign-out successful. }).catch((error) => { // An error happened. });
Web
firebase.auth().signOut().then(() => { // Sign-out successful. }).catch((error) => { // An error happened. });