Autenticação por smartphone

A autenticação por smartphone permite que os usuários façam login no Firebase usando o próprio smartphone como autenticador. Uma mensagem SMS será enviada para o usuário (usando o número de telefone fornecido) contendo um código exclusivo. Depois que o código for autorizado, o usuário poderá fazer login no Firebase.

Os números de telefone que os usuários finais fornecem para autenticação são enviados e armazenados pelo Google para melhorar a prevenção de spam e abusos em nossos serviços, incluindo o Firebase, mas não se limitando a ele. Os desenvolvedores devem garantir que tenham o consentimento do usuário final antes de usar o serviço de login com número de telefone do Firebase Authentication.

O Firebase Phone Authentication não está disponível em todos os países. Consulte as perguntas frequentes para mais informações.

Configuração

Antes de começar a autenticação por smartphone, siga estas etapas:

  1. Ative o Google como um método de login no Console do Firebase.
  2. Android: caso ainda não tenha definido o hash SHA-1 do seu app no Console do Firebase, faça isso. Consulte Como autenticar seu cliente para informações sobre como encontrar o hash SHA-1 do seu app.
  3. iOS: no Xcode, ative as notificações push para seu projeto e verifique se sua chave de autenticação de APNs está configurada com o Firebase Cloud Messaging (FCM). Além disso, é necessário ativar os modos de segundo plano para notificações remotas. Para acessar uma explicação detalhada desta etapa, consulte a documentação Firebase iOS Phone Auth.
  4. Web: verifique se você adicionou o domínio do seu aplicativo ao Console do Firebase, em Domínios de redirecionamento OAuth.

Observação: o login com número de telefone só está disponível para uso em dispositivos reais e na Web. Para testar o fluxo de autenticação em emuladores de dispositivos, consulte Testes.

Uso

O SDK do Firebase Authentication para Flutter oferece duas maneiras individuais de fazer o login de um usuário com um número de telefone. As plataformas nativas (por exemplo, Android e iOS) oferecem funcionalidades diferentes para validar números de telefone da Web. Portanto, existem dois métodos exclusivos para cada plataforma:

  • Plataforma nativa: verifyPhoneNumber
  • Plataforma da Web: signInWithPhoneNumber.

Nativo: verifyPhoneNumber

Em plataformas nativas, o número de telefone do usuário precisa ser verificado primeiro para que o usuário possa fazer login ou vincular a conta a uma PhoneAuthCredential.

Primeiro, solicite o número de telefone do usuário. Depois, chame o método verifyPhoneNumber():

await FirebaseAuth.instance.verifyPhoneNumber(
  phoneNumber: '+44 7123 123 456',
  verificationCompleted: (PhoneAuthCredential credential) {},
  verificationFailed: (FirebaseAuthException e) {},
  codeSent: (String verificationId, int? resendToken) {},
  codeAutoRetrievalTimeout: (String verificationId) {},
);

Há quatro callbacks separados que você precisa processar. Cada um vai determinar como atualizar a IU do aplicativo:

  1. verificationCompleted: gerenciamento automático do código SMS em dispositivos Android.
  2. verificationFailed: lida com os eventos de falha, como números de telefone inválidos ou se a cota de SMS foi excedida.
  3. codeSent: gerencia quando um código é enviado do dispositivo para o Firebase, usado para solicitar que os usuários digitem o código.
  4. codeAutoRetrievalTimeout: processar um tempo limite quando o processamento automático de código SMS falhar.

verificationCompleted

Esse gerenciador só será chamado em dispositivos Android compatíveis com a resolução automática de código SMS.

Quando o código SMS é entregue ao dispositivo, o Android verifica automaticamente esse código sem exigir que o usuário insira manualmente o código. Se esse evento ocorrer, um PhoneAuthCredential será fornecido automaticamente, que pode ser usado para fazer login ou vincular o número de telefone do usuário.

FirebaseAuth auth = FirebaseAuth.instance;

await auth.verifyPhoneNumber(
  phoneNumber: '+44 7123 123 456',
  verificationCompleted: (PhoneAuthCredential credential) async {
    // ANDROID ONLY!

    // Sign the user in (or link) with the auto-generated credential
    await auth.signInWithCredential(credential);
  },
);

verificationFailed

Se o Firebase retornar um erro, por exemplo, para um número de telefone incorreto ou se a cota de SMS do projeto for excedida, um FirebaseAuthException será enviado para este gerenciador. Nesse caso, você pediria que o usuário falhasse dependendo do código de erro.

FirebaseAuth auth = FirebaseAuth.instance;

await auth.verifyPhoneNumber(
  phoneNumber: '+44 7123 123 456',
  verificationFailed: (FirebaseAuthException e) {
    if (e.code == 'invalid-phone-number') {
      print('The provided phone number is not valid.');
    }

    // Handle other errors
  },
);

codeSent

Quando o Firebase envia um código SMS para o dispositivo, esse gerenciador é acionado com umverificationId e resendToken (um resendToken é compatível somente com dispositivos Android. Dispositivos iOSsempre retornam um valor null).

Depois disso, é uma boa hora para atualizar a IU do aplicativo e solicitar que o usuário digite o código SMS esperado. Depois que o código SMS for inserido, você poderá combinar a identificação da verificação com o código SMS para criar um novo PhoneAuthCredential:

FirebaseAuth auth = FirebaseAuth.instance;

await auth.verifyPhoneNumber(
  phoneNumber: '+44 7123 123 456',
  codeSent: (String verificationId, int? resendToken) async {
    // Update the UI - wait for the user to enter the SMS code
    String smsCode = 'xxxx';

    // Create a PhoneAuthCredential with the code
    PhoneAuthCredential credential = PhoneAuthProvider.credential(verificationId: verificationId, smsCode: smsCode);

    // Sign the user in (or link) with the credential
    await auth.signInWithCredential(credential);
  },
);

Por padrão, o Firebase não reenvia uma nova mensagem SMS se ela tiver sido enviada recentemente. No entanto, é possível modificar esse comportamento chamando o método verifyPhoneNumber com o token de reenvio ao argumento forceResendingToken. Se for bem-sucedida, a mensagem SMS será reenviada.

codeAutoRetrievalTimeout

Em dispositivos Android compatíveis com a resolução automática de código SMS, esse gerenciador será chamado se o dispositivo não resolver uma mensagem SMS automaticamente em um determinado período. Após esse período, o dispositivo não tentará mais resolver nenhuma mensagem recebida.

Por padrão, o dispositivo aguarda 30 segundos, mas isso pode ser personalizado com o argumento timeout:

FirebaseAuth auth = FirebaseAuth.instance;

await auth.verifyPhoneNumber(
  phoneNumber: '+44 7123 123 456',
  timeout: const Duration(seconds: 60),
  codeAutoRetrievalTimeout: (String verificationId) {
    // Auto-resolution timed out...
  },
);

Web: signInWithPhoneNumber

Nas plataformas da Web, os usuários podem fazer login confirmando que têm acesso a um telefone digitando o código SMS enviado para o número de telefone fornecido. Para aumentar a segurança e a prevenção contra spam, os usuários precisam preencher um widget do Google reCAPTCHA para provar que são humanos. Depois da confirmação, o código SMS será enviado.

O SDK do Firebase Authentication para Flutter gerenciará o widget reCAPTCHA por padrão, mas oferece controle sobre como ele é exibido e configurado, se necessário. Para começar, chame o método signInWithPhoneNumber com o número de telefone.

FirebaseAuth auth = FirebaseAuth.instance;

// Wait for the user to complete the reCAPTCHA & for an SMS code to be sent.
ConfirmationResult confirmationResult = await auth.signInWithPhoneNumber('+44 7123 123 456');

Chamar o método acionará primeiro o widget reCAPTCHA para ser exibido. O usuário precisa concluir o teste antes de enviar um código SMS. Depois de concluído, é possível fazer o login do usuário fornecendo o código SMS para o método confirm na resposta ConfirmationResult resolvida:

UserCredential userCredential = await confirmationResult.confirm('123456');

Assim como outros fluxos de login, um login bem-sucedido acionará todos os listeners de estados de autenticação inscritos no aplicativo.

Configuração do reCAPTCHA

O widget reCAPTCHA é um fluxo totalmente gerenciado que fornece segurança para seu aplicativo da Web.

O segundo argumento de signInWithPhoneNumber aceita uma instância RecaptchaVerifier opcional que pode ser usada para gerenciar o widget. Por padrão, o widget é renderizado como invisível quando o fluxo de login é acionado. Um widget "invisível" aparecerá como um modal de página inteira sobre o aplicativo.

No entanto, é possível mostrar um widget inline que o usuário precisa pressionar explicitamente para fazer a verificação.

Para adicionar um widget in-line, especifique um ID de elemento DOM para o argumento container da instância RecaptchaVerifier. O elemento precisa existir e estar vazio. Caso contrário, um erro será gerado. Se nenhum argumento container for fornecido, o widget será renderizado como "invisível".

ConfirmationResult confirmationResult = await auth.signInWithPhoneNumber('+44 7123 123 456', RecaptchaVerifier(
  container: 'recaptcha',
  size: RecaptchaVerifierSize.compact,
  theme: RecaptchaVerifierTheme.dark,
));

É possível mudar o tamanho e o tema, personalizando os argumentos size e theme, conforme mostrado acima.

Também é possível detectar eventos, como se o reCAPTCHA foi concluído pelo usuário, se o reCAPTCHA expirou ou se um erro foi gerado:

RecaptchaVerifier(
  onSuccess: () => print('reCAPTCHA Completed!'),
  onError: (FirebaseAuthException error) => print(error),
  onExpired: () => print('reCAPTCHA Expired!'),
);

Teste

O Firebase oferece suporte para testes locais de números de telefone:

  1. No Console do Firebase, selecione o provedor de autenticação "Telefone" e clique na lista suspensa "Números de telefone para testes".
  2. Insira um novo número de telefone (por exemplo, +44 7444 555666) e um código de teste (por exemplo, 123456).

Se você fornecer um número de telefone de teste para os métodos verifyPhoneNumber ou signInWithPhoneNumber, nenhum SMS será enviado. Em vez disso, forneça o código de teste diretamente ao PhoneAuthProvider ou com o gerenciador de resultados da confirmação de signInWithPhoneNumber.