Autenticar com o Firebase usando link por e-mail no JavaScript

Use o Firebase Authentication para fazer o login de um usuário por meio de 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úmeras vantagens:

  • Inscrição e login menos complicados.
  • Menos chances de reutilizar senhas entre os aplicativos, o que poderia 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úmero de telefone ou conta em redes sociais.
  • O usuário faz login com segurança sem precisar fornecer ou lembrar uma senha, ações que podem ser incômodas em dispositivos móveis.
  • O usuário que já tiver feito login com um identificador de e-mail (senha ou federado) poderá se conectar posteriormente 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 ao projeto do JavaScript, se ainda não tiver feito isso.

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:

  1. No Console do Firebase, abra a seção Autenticação.
  2. Na guia Método de login, ative o provedor de E-mail/senha. Lembre-se de que você precisa ativar esse método para poder usar o login por link.
  3. Na mesma seção, ative o método Link do e-mail (login sem senha).
  4. Clique em Salvar.

Para iniciar o fluxo de autenticação, forneça ao usuário uma interface que solicite o endereço de e-mail dele. Depois, chame sendSignInLinkToEmail para solicitar que o Firebase envie o link de autenticação a esse e-mail.

  1. Crie o objeto ActionCodeSettings, que fornece ao Firebase instruções para gerar o link do e-mail. Configure os campos a seguir:

    • url: o link direto a ser incorporado e qualquer estado adicional a ser transmitido junto. É preciso que o domínio do link esteja na lista de permissões de domínios autorizados do Console do Firebase, encontrada na guia Método de login (Autenticação -> Método de login).
    • android e ios: os apps a serem usados quando o usuário abrir o link para fazer login em um dispositivo Android ou iOS. Saiba mais sobre como configurar o Firebase Dynamic Links para abrir links de ação por e-mail via aplicativos para dispositivos móveis.
    • handleCodeInApp: definido como true. É 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.
    • dynamicLinkDomain: quando vários domínios de link dinâmico customizados são definidos em um projeto, especifique qual deles usar se o link precisar ser aberto em um determinado app para dispositivos móveis (por exemplo, example.page.link). Caso contrário, o primeiro domínio será selecionado automaticamente.
    
    var actionCodeSettings = {
      // URL you want to redirect back to. The domain (www.example.com) for this
      // URL must be whitelisted 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 ActionCodeSettings, consulte a seção Como transmitir o estado nas ações de e-mail.

  2. Solicite o e-mail ao usuário.

  3. 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.

    
    firebase.auth().sendSignInLinkToEmail(email, actionCodeSettings)
      .then(function() {
        // 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(function(error) {
        // Some error occurred, you can inspect the code: error.code
      });
    

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 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 existentes 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.


// 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(function(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(function(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 aplicativo para dispositivos móveis

O Firebase Authentication usa o Firebase Dynamic Links 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 aplicativo para Android, consulte este guia.

Para saber mais sobre como processar o login com o link por e-mail em um aplicativo para iOS, consulte este guia.

Também é possível vincular este método de autenticação a um usuário existente. 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:


// 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.linkAndRetrieveDataWithCredential(credential)
  .then(function(usercred) {
    // The provider is now successfully linked.
    // The phone user can now sign in with their phone number or email.
  })
  .catch(function(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.


// 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.reauthenticateAndRetrieveDataWithCredential(credential)
  .then(function(usercred) {
    // The user is now successfully re-authenticated and can execute sensitive
    // operations.
  })
  .catch(function(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.

Caso ambos os logins por senha e por link de e-mail sejam compatíveis, use fetchSignInMethodsForEmail para diferenciar o método de login do usuário. Isso é útil nos fluxos que priorizam identificadores, em que o usuário é solicitado a fornecer o e-mail e precisa escolher o método de login:

// After asking the user for their email.
var email = window.prompt('Please provide your email');
firebase.auth().fetchSignInMethodsForEmail(email)
  .then(function(signInMethods) {
    // This returns the same array as fetchProvidersForEmail but for email
    // provider identified by 'password' string, signInMethods would contain 2
    // different strings:
    // 'emailLink' if the user previously signed in with an email/link
    // 'password' if the user has a password.
    // A user could have both.
    if (signInMethods.indexOf(
            firebase.auth.EmailAuthProvider.EMAIL_PASSWORD_SIGN_IN_METHOD) != -1) {
      // User can sign in with email/password.
    }
     if (signInMethods.indexOf(
             firebase.auth.EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD) != -1) {
       // User can sign in with email/link.
    }
  })
  .catch(function(error) {
    // Some error occurred, you can inspect the code: error.code
  });
}

Conforme descrito acima, e-mail/senha e e-mail/link têm o mesmo firebase.auth.EmailAuthProvider (mesmo PROVIDER_ID), com diferentes métodos de login.

Próximas etapas

Depois que um usuário faz login pela primeira vez, uma nova conta é 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. Ela pode ser usada para identificar um usuário em todos os apps do projeto, independentemente do método de login usado.

  • Nos seus apps, a maneira recomendada para descobrir o status de autenticação do usuário é definir um observador no objeto Auth. Você pode coletar as informações básicas do perfil do usuário do objeto User. Consulte Gerenciar usuários.

  • Nas Regras de segurança do Firebase Realtime Database e do Cloud Storage, é possível usar a variável auth para encontrar o código exclusivo do usuário conectado. Use essa informação para controlar quais dados ele 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:

firebase.auth().signOut().then(function() {
  // Sign-out successful.
}).catch(function(error) {
  // An error happened.
});

Enviar comentários sobre…

Precisa de ajuda? Acesse nossa página de suporte.