O Google tem o compromisso de promover a igualdade racial para as comunidades negras. Saiba como.

Autenticar com o Firebase usando o link de e-mail em JavaScript

Mantenha tudo organizado com as coleções Salve e categorize o conteúdo com base nas suas preferências.

Você pode usar o Firebase Authentication para fazer login de um usuário enviando a ele um e-mail contendo um link, no qual ele pode clicar para fazer login. No processo, o endereço de e-mail do usuário também é verificado.

Há vários benefícios em fazer login por e-mail:

  • Inscrição e login de baixo atrito.
  • Menor risco de reutilização de senha em aplicativos, o que pode prejudicar a segurança até mesmo de senhas bem selecionadas.
  • A capacidade de autenticar um usuário e, ao mesmo tempo, verificar se o usuário é o proprietário legítimo de um endereço de e-mail.
  • Um usuário precisa apenas de uma conta de e-mail acessível para fazer login. Não é necessária a propriedade de um número de telefone ou conta de mídia social.
  • Um usuário pode fazer login com segurança sem a necessidade de fornecer (ou lembrar) uma senha, o que pode ser complicado em um dispositivo móvel.
  • Um usuário existente que fez login anteriormente com um identificador de e-mail (senha ou federado) pode ser atualizado para entrar apenas com o e-mail. Por exemplo, um usuário que esqueceu sua senha ainda pode entrar sem precisar redefinir sua senha.

Antes de você começar

Caso ainda não tenha feito isso, copie o snippet de inicialização do console do Firebase para seu projeto, conforme descrito em Adicionar o Firebase ao seu projeto JavaScript .

Para fazer login de usuários por link de e-mail, você deve primeiro ativar o provedor de e-mail e o método de login do link de e-mail para seu projeto do Firebase:

  1. No console do Firebase , abra a seção Auth .
  2. Na guia Método de login , habilite o provedor de e- mail/senha . Observe que o login por e-mail/senha deve estar habilitado para usar o login por link de e-mail.
  3. Na mesma seção, habilite o método de login do link de e-mail (entrada sem senha) .
  4. Clique em Salvar .

Para iniciar o fluxo de autenticação, apresente ao usuário uma interface que solicita que o usuário forneça seu endereço de e-mail e chame sendSignInLinkToEmail para solicitar que o Firebase envie o link de autenticação para o e-mail do usuário.

  1. Construa o objeto ActionCodeSettings , que fornece ao Firebase instruções sobre como construir o link de e-mail. Defina os seguintes campos:

    • url : O link direto a ser incorporado e qualquer estado adicional a ser transmitido. O domínio do link deve ser adicionado à lista de domínios autorizados do Firebase Console, que pode ser encontrada na guia Método de login (Autenticação -> Método de login).
    • android e ios : os aplicativos a serem usados ​​quando o link de login é aberto em um dispositivo Android ou Apple. Saiba mais sobre como configurar o Firebase Dynamic Links para abrir links de ação de e-mail por meio de aplicativos para dispositivos móveis.
    • handleCodeInApp : Defina como true. A operação de login deve sempre ser concluída no aplicativo, ao contrário de outras ações de e-mail fora da banda (redefinição de senha e verificações de e-mail). Isso ocorre porque, no final do fluxo, espera-se que o usuário esteja conectado e seu estado de autenticação persista no aplicativo.
    • dynamicLinkDomain : quando vários domínios de link dinâmico personalizados são definidos para um projeto, especifique qual usar quando o link deve ser aberto por meio de um aplicativo móvel especificado (por exemplo, example.page.link ). Caso contrário, o primeiro domínio é selecionado automaticamente.

      Web version 9

      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'
        },
        dynamicLinkDomain: 'example.page.link'
      };

      Web version 8

      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 ActionCodeSettings, consulte a seção Passing State in Email Actions .

  2. Peça ao usuário seu e-mail.

  3. Envie o link de autenticação para o e-mail do usuário e salve o e-mail do usuário caso o usuário conclua o login de e-mail no mesmo dispositivo.

    Web version 9

    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 version 8

    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;
        // ...
      });

Preocupações com segurança

Para evitar que um link de login seja usado para fazer login como um usuário não intencional ou em um dispositivo não intencional, o Firebase Auth exige que o endereço de e-mail do usuário seja fornecido ao concluir o fluxo de login. Para que o login seja bem-sucedido, esse endereço de e-mail deve corresponder ao endereço para o qual o link de login foi enviado originalmente.

Você pode simplificar esse fluxo para usuários que abrem o link de entrada no mesmo dispositivo em que solicitam o link, armazenando seu endereço de e-mail localmente - por exemplo, usando localStorage ou cookies - ao enviar o e-mail de entrada. Em seguida, use esse endereço para concluir o fluxo. Não passe o e-mail do usuário nos parâmetros de URL de redirecionamento e reutilize-o, pois isso pode permitir injeções de sessão.

Após a conclusão do login, qualquer mecanismo de login anterior não verificado será removido do usuário e todas as sessões existentes serão invalidadas. Por exemplo, se alguém criou anteriormente uma conta não verificada com o mesmo e-mail e senha, a senha do usuário será removida para impedir que o falsificador que reivindicou a propriedade e criou essa conta não verificada entre novamente com o e-mail e a senha não verificados.

Certifique-se também de usar um URL HTTPS em produção para evitar que seu link seja potencialmente interceptado por servidores intermediários.

Concluindo o login em uma página da Web

O formato do link direto do link de e-mail é o mesmo que o formato usado para ações de e-mail fora de banda (verificação de e-mail, redefinição de senha e revogação de alteração de e-mail). O Firebase Auth simplifica essa verificação fornecendo a API isSignInWithEmailLink para verificar se um link é um link de login com e-mail.

Para concluir o login na página inicial, chame signInWithEmailLink com o e-mail do usuário e o link de e-mail real que contém o código de uso único.

Web version 9

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 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.
    });
}

Web version 8

// 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.
    });
}

Concluindo o login em um aplicativo para dispositivos móveis

O Firebase Authentication usa o Firebase Dynamic Links para enviar o link de e-mail para um dispositivo móvel. Para concluir o login por meio de aplicativo móvel, o aplicativo deve ser configurado para detectar o link do aplicativo de entrada, analisar o link direto subjacente e concluir o login conforme feito via fluxo da web.

Para saber mais sobre como lidar com o login com link de e-mail em um aplicativo Android, consulte o guia do Android .

Para saber mais sobre como lidar com o login com link de e-mail em um aplicativo da Apple, consulte o guia de plataformas da Apple .

Você também pode vincular esse método de autenticação a um usuário existente. Por exemplo, um usuário previamente autenticado com outro provedor, como um número de telefone, pode adicionar esse método de login à sua conta existente.

A diferença estaria na segunda metade da operação:

Web version 9

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 version 8

// 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.
  });

Isso também pode ser usado para autenticar novamente um usuário de link de e-mail antes de executar uma operação confidencial.

Web version 9

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 version 8

// 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, como o fluxo pode terminar em um dispositivo diferente no qual o usuário original não estava conectado, esse fluxo pode não ser concluído. Nesse caso, um erro pode ser mostrado ao usuário para forçá-lo a abrir o link no mesmo dispositivo. Algum estado pode ser passado no link para fornecer informações sobre o tipo de operação e o uid do usuário.

Caso você ofereça suporte a login baseado em senha e link com e-mail, para diferenciar o método de login para um usuário de senha/link, use fetchSignInMethodsForEmail . Isso é útil para fluxos que priorizam o identificador em que o usuário é solicitado primeiro a fornecer seu e-mail e, em seguida, apresentado o método de login:

Web version 9

import { getAuth, fetchSignInMethodsForEmail, EmailAuthProvider} from "firebase/auth";

// After asking the user for their email.
const email = window.prompt('Please provide your email');

const auth = getAuth();
fetchSignInMethodsForEmail(auth, email)
  .then((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(EmailAuthProvider.EMAIL_PASSWORD_SIGN_IN_METHOD) != -1) {
      // User can sign in with email/password.
    }
    if (signInMethods.indexOf(EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD) != -1) {
      // User can sign in with email/link.
    }
  })
  .catch((error) => {
    // Some error occurred, you can inspect the code: error.code
  });

Web version 8

// After asking the user for their email.
var email = window.prompt('Please provide your email');
firebase.auth().fetchSignInMethodsForEmail(email)
  .then((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((error) => {
    // Some error occurred, you can inspect the code: error.code
  });

Conforme descrito acima, email/senha e email/link são considerados o mesmo firebase.auth.EmailAuthProvider (mesmo PROVIDER_ID ) com diferentes métodos de login.

Próximos passos

Depois que um usuário entra pela primeira vez, uma nova conta de usuário é criada e vinculada às credenciais, ou seja, o nome de usuário e a senha, o número de telefone ou as informações do provedor de autenticação com as quais o usuário fez login. Essa nova conta é armazenada como parte do seu projeto do Firebase e pode ser usada para identificar um usuário em todos os aplicativos do projeto, independentemente de como o usuário faça login.

  • Em seus aplicativos, a maneira recomendada de saber o status de autenticação de seu usuário é definir um observador no objeto Auth . Você pode então obter as informações básicas do perfil do User do objeto Usuário. Consulte Gerenciar usuários .

  • Nas regras de segurança do Firebase Realtime Database e do Cloud Storage , você pode obter o ID de usuário exclusivo do usuário conectado a partir da variável de auth e usá-lo para controlar quais dados um usuário pode acessar.

Você pode permitir que os usuários façam login no seu aplicativo usando vários provedores de autenticação vinculando as credenciais do provedor de autenticação a uma conta de usuário existente.

Para desconectar um usuário, chame signOut :

Web version 9

import { getAuth, signOut } from "firebase/auth";

const auth = getAuth();
signOut(auth).then(() => {
  // Sign-out successful.
}).catch((error) => {
  // An error happened.
});

Web version 8

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