Autenticar no Firebase com um número de telefone usando JavaScript,Autenticar no Firebase com um número de telefone usando JavaScript

Você pode usar o Firebase Authentication para fazer login de um usuário enviando uma mensagem SMS para o telefone do usuário. O usuário faz login usando um código único contido na mensagem SMS.

A maneira mais fácil de adicionar login por número de telefone ao seu aplicativo é usar FirebaseUI , que inclui um widget de login drop-in que implementa fluxos de login para login por número de telefone, bem como login federado e baseado em senha -em. Este documento descreve como implementar um fluxo de login por número de telefone usando o SDK do Firebase.

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 .

Preocupações com segurança

A autenticação usando apenas um número de telefone, embora conveniente, é menos segura do que outros métodos disponíveis, porque a posse de um número de telefone pode ser facilmente transferida entre usuários. Além disso, em dispositivos com vários perfis de usuário, qualquer usuário que possa receber mensagens SMS poderá fazer login em uma conta usando o número de telefone do dispositivo.

Se você usar o login baseado em número de telefone em seu aplicativo, deverá oferecê-lo junto com métodos de login mais seguros e informar os usuários sobre as desvantagens de segurança do uso do login por número de telefone.

Ative o login com número de telefone para seu projeto do Firebase

Para fazer login de usuários por SMS, primeiro você precisa ativar o método de login por número de telefone para seu projeto do Firebase:

  1. No console do Firebase , abra a seção Autenticação .
  2. Na página Método de login , habilite o método de login com número de telefone .
  3. Na mesma página, se o domínio que hospedará seu aplicativo não estiver listado na seção Domínios de redirecionamento OAuth , adicione seu domínio.

A cota de solicitações de login por número de telefone do Firebase é alta o suficiente para que a maioria dos aplicativos não seja afetada. No entanto, se você precisar conectar um volume muito grande de usuários com autenticação por telefone, talvez seja necessário atualizar seu plano de preços. Veja a página de preços .

Configure o verificador reCAPTCHA

Antes de poder fazer login dos usuários com seus números de telefone, você deve configurar o verificador reCAPTCHA do Firebase. O Firebase usa o reCAPTCHA para evitar abusos, como garantir que a solicitação de verificação do número de telefone venha de um dos domínios permitidos do seu aplicativo.

Você não precisa configurar manualmente um cliente reCAPTCHA; quando você usa o objeto RecaptchaVerifier do SDK do Firebase, o Firebase cria e gerencia automaticamente quaisquer chaves e segredos de cliente necessários.

O objeto RecaptchaVerifier suporta reCAPTCHA invisível , que muitas vezes pode verificar o usuário sem exigir qualquer ação do usuário, bem como o widget reCAPTCHA, que sempre requer interação do usuário para ser concluído com êxito.

O reCAPTCHA renderizado subjacente pode ser localizado de acordo com a preferência do usuário, atualizando o código do idioma na instância Auth antes de renderizar o reCAPTCHA. A referida localização também se aplicará à mensagem SMS enviada ao usuário, contendo o código de verificação.

Web modular API

import { getAuth } from "firebase/auth";

const auth = getAuth();
auth.languageCode = 'it';
// To apply the default browser preference instead of explicitly setting it.
// auth.useDeviceLanguage();

Web namespaced API

firebase.auth().languageCode = 'it';
// To apply the default browser preference instead of explicitly setting it.
// firebase.auth().useDeviceLanguage();

Use reCAPTCHA invisível

Para usar um reCAPTCHA invisível, crie um objeto RecaptchaVerifier com o parâmetro size definido como invisible , especificando o ID do botão que envia seu formulário de login. Por exemplo:

Web modular API

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

const auth = getAuth();
window.recaptchaVerifier = new RecaptchaVerifier(auth, 'sign-in-button', {
  'size': 'invisible',
  'callback': (response) => {
    // reCAPTCHA solved, allow signInWithPhoneNumber.
    onSignInSubmit();
  }
});

Web namespaced API

window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('sign-in-button', {
  'size': 'invisible',
  'callback': (response) => {
    // reCAPTCHA solved, allow signInWithPhoneNumber.
    onSignInSubmit();
  }
});

Use o widget reCAPTCHA

Para usar o widget reCAPTCHA visível, crie um elemento em sua página para conter o widget e, em seguida, crie um objeto RecaptchaVerifier , especificando o ID do contêiner ao fazer isso. Por exemplo:

Web modular API

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

const auth = getAuth();
window.recaptchaVerifier = new RecaptchaVerifier(auth, 'recaptcha-container', {});

Web namespaced API

window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container');

Opcional: especifique parâmetros reCAPTCHA

Opcionalmente, você pode definir funções de retorno de chamada no objeto RecaptchaVerifier que são chamadas quando o usuário resolve o reCAPTCHA ou o reCAPTCHA expira antes de o usuário enviar o formulário:

Web modular API

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

const auth = getAuth();
window.recaptchaVerifier = new RecaptchaVerifier(auth, 'recaptcha-container', {
  'size': 'normal',
  'callback': (response) => {
    // reCAPTCHA solved, allow signInWithPhoneNumber.
    // ...
  },
  'expired-callback': () => {
    // Response expired. Ask user to solve reCAPTCHA again.
    // ...
  }
});

Web namespaced API

window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container', {
  'size': 'normal',
  'callback': (response) => {
    // reCAPTCHA solved, allow signInWithPhoneNumber.
    // ...
  },
  'expired-callback': () => {
    // Response expired. Ask user to solve reCAPTCHA again.
    // ...
  }
});

Opcional: pré-renderize o reCAPTCHA

Se você quiser pré-renderizar o reCAPTCHA antes de enviar uma solicitação de login, chame render :

Web modular API

recaptchaVerifier.render().then((widgetId) => {
  window.recaptchaWidgetId = widgetId;
});

Web namespaced API

recaptchaVerifier.render().then((widgetId) => {
  window.recaptchaWidgetId = widgetId;
});

Depois que render for resolvida, você obterá o ID do widget do reCAPTCHA, que pode ser usado para fazer chamadas para a API do reCAPTCHA :

Web modular API

const recaptchaResponse = grecaptcha.getResponse(recaptchaWidgetId);

Web namespaced API

const recaptchaResponse = grecaptcha.getResponse(recaptchaWidgetId);

Envie um código de verificação para o telefone do usuário

Para iniciar o login com número de telefone, apresente ao usuário uma interface que solicita que ele forneça seu número de telefone e, em seguida, ligue para signInWithPhoneNumber para solicitar que o Firebase envie um código de autenticação ao telefone do usuário por SMS:

  1. Obtenha o número de telefone do usuário.

    Os requisitos legais variam, mas como prática recomendada e para definir expectativas para seus usuários, você deve informá-los de que, se usarem login por telefone, poderão receber uma mensagem SMS para verificação e serão aplicadas taxas padrão.

  2. Chame signInWithPhoneNumber , passando para ele o número de telefone do usuário e o RecaptchaVerifier que você criou anteriormente.

    Web modular API

    import { getAuth, signInWithPhoneNumber } from "firebase/auth";
    
    const phoneNumber = getPhoneNumberFromUserInput();
    const appVerifier = window.recaptchaVerifier;
    
    const auth = getAuth();
    signInWithPhoneNumber(auth, phoneNumber, appVerifier)
        .then((confirmationResult) => {
          // SMS sent. Prompt user to type the code from the message, then sign the
          // user in with confirmationResult.confirm(code).
          window.confirmationResult = confirmationResult;
          // ...
        }).catch((error) => {
          // Error; SMS not sent
          // ...
        });

    Web namespaced API

    const phoneNumber = getPhoneNumberFromUserInput();
    const appVerifier = window.recaptchaVerifier;
    firebase.auth().signInWithPhoneNumber(phoneNumber, appVerifier)
        .then((confirmationResult) => {
          // SMS sent. Prompt user to type the code from the message, then sign the
          // user in with confirmationResult.confirm(code).
          window.confirmationResult = confirmationResult;
          // ...
        }).catch((error) => {
          // Error; SMS not sent
          // ...
        });
    Se signInWithPhoneNumber resultar em erro, redefina o reCAPTCHA para que o usuário possa tentar novamente:
    grecaptcha.reset(window.recaptchaWidgetId);
    
    // Or, if you haven't stored the widget ID:
    window.recaptchaVerifier.render().then(function(widgetId) {
      grecaptcha.reset(widgetId);
    });
    

O método signInWithPhoneNumber emite o desafio reCAPTCHA para o usuário e, se o usuário passar no desafio, solicita que o Firebase Authentication envie uma mensagem SMS contendo um código de verificação para o telefone do usuário.

Faça login no usuário com o código de verificação

Após a chamada para signInWithPhoneNumber ser bem-sucedida, solicite ao usuário que digite o código de verificação recebido por SMS. Em seguida, faça login do usuário passando o código para o método confirm do objeto ConfirmationResult que foi passado para o manipulador de atendimento de signInWithPhoneNumber (ou seja, seu bloco then ). Por exemplo:

Web modular API

const code = getCodeFromUserInput();
confirmationResult.confirm(code).then((result) => {
  // User signed in successfully.
  const user = result.user;
  // ...
}).catch((error) => {
  // User couldn't sign in (bad verification code?)
  // ...
});

Web namespaced API

const code = getCodeFromUserInput();
confirmationResult.confirm(code).then((result) => {
  // User signed in successfully.
  const user = result.user;
  // ...
}).catch((error) => {
  // User couldn't sign in (bad verification code?)
  // ...
});

Se a chamada para confirm for bem-sucedida, o usuário será conectado com êxito.

Obtenha o objeto AuthCredential intermediário

Se você precisar obter um objeto AuthCredential para a conta do usuário, passe o código de verificação do resultado da confirmação e o código de verificação para PhoneAuthProvider.credential em vez de chamar confirm :

var credential = firebase.auth.PhoneAuthProvider.credential(confirmationResult.verificationId, code);

Em seguida, você pode fazer login do usuário com a credencial:

firebase.auth().signInWithCredential(credential);

Teste com números de telefone fictícios

Você pode configurar números de telefone fictícios para desenvolvimento por meio do Console do Firebase. Testar com números de telefone fictícios oferece estes benefícios:

  • Teste a autenticação do número de telefone sem consumir sua cota de uso.
  • Teste a autenticação do número de telefone sem enviar uma mensagem SMS real.
  • Execute testes consecutivos com o mesmo número de telefone sem ser limitado. Isso minimiza o risco de rejeição durante o processo de revisão da App Store se o revisor usar o mesmo número de telefone para o teste.
  • Teste prontamente em ambientes de desenvolvimento sem nenhum esforço adicional, como a capacidade de desenvolver em um simulador iOS ou em um emulador Android sem o Google Play Services.
  • Escreva testes de integração sem ser bloqueado por verificações de segurança normalmente aplicadas em números de telefone reais em um ambiente de produção.

Os números de telefone fictícios devem atender a estes requisitos:

  1. Certifique-se de usar números de telefone que sejam realmente fictícios e que ainda não existam. O Firebase Authentication não permite definir números de telefone existentes usados ​​por usuários reais como números de teste. Uma opção é usar números prefixados 555 como números de telefone de teste nos EUA, por exemplo: +1 650-555-3434
  2. Os números de telefone devem ser formatados corretamente quanto ao comprimento e outras restrições. Eles ainda passarão pela mesma validação que o número de telefone de um usuário real.
  3. Você pode adicionar até 10 números de telefone para desenvolvimento.
  4. Use números/códigos de telefone de teste que sejam difíceis de adivinhar e altere-os com frequência.

Crie números de telefone e códigos de verificação fictícios

  1. No console do Firebase , abra a seção Autenticação .
  2. Na guia Método de login , habilite a operadora de telefonia, caso ainda não o tenha feito.
  3. Abra o menu acordeão Números de telefone para teste .
  4. Forneça o número de telefone que deseja testar, por exemplo: +1 650-555-3434 .
  5. Forneça o código de verificação de 6 dígitos para esse número específico, por exemplo: 654321 .
  6. Adicione o número. Se houver necessidade, você pode excluir o número de telefone e seu código passando o mouse sobre a linha correspondente e clicando no ícone da lixeira.

Teste manual

Você pode começar a usar diretamente um número de telefone fictício em seu aplicativo. Isso permite que você execute testes manuais durante os estágios de desenvolvimento sem enfrentar problemas de cota ou limitação. Você também pode testar diretamente de um simulador iOS ou emulador Android sem o Google Play Services instalado.

Quando você fornece o número de telefone fictício e envia o código de verificação, nenhum SMS real é enviado. Em vez disso, você precisa fornecer o código de verificação configurado anteriormente para concluir o login.

Após a conclusão do login, um usuário do Firebase é criado com esse número de telefone. O usuário tem o mesmo comportamento e propriedades de um usuário de número de telefone real e pode acessar o Realtime Database/Cloud Firestore e outros serviços da mesma maneira. O token de identificação gerado durante esse processo tem a mesma assinatura de um usuário de número de telefone real.

Outra opção é definir uma função de teste por meio de declarações personalizadas para esses usuários para diferenciá-los como usuários falsos se você quiser restringir ainda mais o acesso.

Teste de integração

Além dos testes manuais, o Firebase Authentication fornece APIs para ajudar a escrever testes de integração para testes de autenticação por telefone. Essas APIs desativam a verificação de aplicativos, desativando o requisito reCAPTCHA na web e notificações push silenciosas no iOS. Isso torna os testes de automação possíveis nesses fluxos e mais fáceis de implementar. Além disso, eles ajudam a fornecer a capacidade de testar fluxos de verificação instantâneos no Android.

Na web, defina appVerificationDisabledForTesting como true antes de renderizar firebase.auth.RecaptchaVerifier . Isso resolve o reCAPTCHA automaticamente, permitindo passar o número de telefone sem resolvê-lo manualmente. Observe que, mesmo que o reCAPTCHA esteja desativado, o uso de um número de telefone não fictício ainda não conseguirá concluir o login. Somente números de telefone fictícios podem ser usados ​​com esta API.

// Turn off phone auth app verification.
firebase.auth().settings.appVerificationDisabledForTesting = true;

var phoneNumber = "+16505554567";
var testVerificationCode = "123456";

// This will render a fake reCAPTCHA as appVerificationDisabledForTesting is true.
// This will resolve after rendering without app verification.
var appVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container');
// signInWithPhoneNumber will call appVerifier.verify() which will resolve with a fake
// reCAPTCHA response.
firebase.auth().signInWithPhoneNumber(phoneNumber, appVerifier)
    .then(function (confirmationResult) {
      // confirmationResult can resolve with the fictional testVerificationCode above.
      return confirmationResult.confirm(testVerificationCode)
    }).catch(function (error) {
      // Error; SMS not sent
      // ...
    });

Verificadores simulados de aplicativos reCAPTCHA visíveis e invisíveis se comportam de maneira diferente quando a verificação de aplicativos está desativada:

  • ReCAPTCHA visível : quando o reCAPTCHA visível é renderizado via appVerifier.render() , ele se resolve automaticamente após uma fração de segundo de atraso. Isso equivale a um usuário clicar no reCAPTCHA imediatamente após a renderização. A resposta do reCAPTCHA expirará após algum tempo e será resolvida automaticamente novamente.
  • ReCAPTCHA invisível : O reCAPTCHA invisível não é resolvido automaticamente na renderização e, em vez disso, o faz na chamada appVerifier.verify() ou quando o botão âncora do reCAPTCHA é clicado após uma fração de segundo de atraso. Da mesma forma, a resposta expirará após algum tempo e só será resolvida automaticamente após a chamada appVerifier.verify() ou quando o botão âncora do reCAPTCHA for clicado novamente.

Sempre que um reCAPTCHA simulado é resolvido, a função de retorno de chamada correspondente é acionada conforme esperado com a resposta falsa. Se um retorno de chamada de expiração também for especificado, ele será acionado na expiração.

Próximos passos

Depois que um usuário faz login pela primeira vez, uma nova conta de usuário é criada e vinculada às credenciais (ou seja, nome de usuário e senha, número de telefone ou 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 seu projeto, independentemente de como o usuário faz login.

  • Em seus aplicativos, a maneira recomendada de saber o status de autenticação do seu usuário é definir um observador no objeto Auth . Você pode então obter as informações básicas do perfil do usuário no objeto User . 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 na variável 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 modular API

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

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

Web namespaced API

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