Ir para o console

Autenticar com o Firebase no Android usando um número de telefone

Use o Firebase Authentication para fazer o login de um usuário. Basta enviar uma mensagem SMS para o telefone dele. O usuário faz login com um código de uso único contido na mensagem SMS.

A maneira mais fácil de adicionar o login com número de telefone ao app é usar a FirebaseUI. Ela inclui um widget drop-in que implementa fluxos para logins com número de telefone, bem como logins por senha ou federados. Este documento descreve como implementar um fluxo de login com número de telefone por meio do SDK do Firebase.

Antes de começar

  1. Adicione o Firebase ao seu projeto do Android.
  2. Adicione a dependência do Firebase Authentication ao seu arquivo build.gradle de nível de aplicativo:
    implementation 'com.google.firebase:firebase-auth:16.1.0'
  3. Caso você ainda não tenha conectado o app ao seu projeto do Firebase, faça isso no Console do Firebase.
  4. Configure o hash SHA-1 do app no Console do Firebase se ainda não tiver feito isso. Consulte Como autenticar seu cliente para saber como encontrar o hash SHA-1 do seu app.

Além disso, é necessário ter um dispositivo físico para fazer login com número de telefone. Esse processo não funciona em emuladores.

Preocupações com a segurança

A autenticação usando apenas um número de telefone é conveniente, porém menos segura do que os outros métodos disponíveis, já que um número de telefone pode ser facilmente transferido entre usuários. Além disso, em dispositivos com vários perfis de usuário, qualquer um que receba mensagens SMS pode fazer login em uma conta usando o número de telefone do dispositivo.

Caso use o login por número de telefone no seu app, você precisa oferecê-lo junto com métodos de login mais seguros e informar aos usuários as implicações de segurança do uso desse tipo de login.

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

Para fazer login de usuários por SMS, ative primeiro o método de login com número de telefone para o projeto do Firebase:

  1. No Console do Firebase, abra a seção Authentication.
  2. Na página Método de login, ative o método de login por Número de telefone.

A cota de solicitação de login com número de telefone do Firebase é alta o suficiente para evitar que a maioria dos apps seja afetada. No entanto, se for necessário fazer login de um grande volume de usuários com autenticação por telefone, atualize o plano de preços. Consulte a página de preços.

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

Para iniciar o login com número de telefone, mostre ao usuário uma interface onde ele precisará inserir o número. Os requisitos legais variam, mas como prática recomendada e para definir as expectativas dos usuários, informe a eles que, se fizerem login com telefone, poderão receber uma mensagem SMS para verificação. Além disso, poderão ser cobrados por esse serviço.

Em seguida, passe o número de telefone deles para o método PhoneAuthProvider.verifyPhoneNumber. Dessa forma, você solicita que o Firebase verifique essa informação. Exemplo:

Java
Android

PhoneAuthProvider.getInstance().verifyPhoneNumber(
        phoneNumber,        // Phone number to verify
        60,                 // Timeout duration
        TimeUnit.SECONDS,   // Unit of timeout
        this,               // Activity (for callback binding)
        mCallbacks);        // OnVerificationStateChangedCallbacks

Kotlin
Android

PhoneAuthProvider.getInstance().verifyPhoneNumber(
        phoneNumber,      // Phone number to verify
        60,               // Timeout duration
        TimeUnit.SECONDS, // Unit of timeout
        this,             // Activity (for callback binding)
        callbacks) // OnVerificationStateChangedCallbacks

O método verifyPhoneNumber é reentrante: se você o chamar várias vezes, como no método onStart de uma atividade, o verifyPhoneNumber não enviará um segundo SMS a menos que o tempo limite da solicitação original tenha expirado.

Você pode usar esse comportamento para retomar o processo de login com número de telefone caso o app seja fechado antes de o usuário fazer login. Por exemplo, enquanto o usuário usa o app de SMS. Depois de chamar verifyPhoneNumber, defina uma sinalização para indicar que a verificação está em andamento. Em seguida, salve a sinalização no método onSaveInstanceState da sua atividade e restaure-a em onRestoreInstanceState. Por fim, veja se a verificação já está em andamento no método onStart da sua atividade. Em caso afirmativo, chame verifyPhoneNumber novamente. Lembre-se de limpar a sinalização depois da conclusão ou falha da verificação. Consulte Retornos de chamada de verificação.

Para gerenciar facilmente a rotação da tela e outras instâncias de reinicializações da atividade, passe-a para o método verifyPhoneNumber. Os retornos de chamada serão desconectados automaticamente quando a atividade for interrompida. Assim, você pode escrever o código de transição da IU livremente nos métodos de retorno de chamada.

Para localizar a mensagem SMS enviada pelo Firebase, é possível também especificar o idioma de autenticação por meio do método setLanguageCode na sua instância de Auth.

Java
Android

auth.setLanguageCode("fr");
// To apply the default app language instead of explicitly setting it.
// auth.useAppLanguage();

Kotlin
Android

auth.setLanguageCode("fr")
// To apply the default app language instead of explicitly setting it.
// auth.useAppLanguage()

Quando você chama PhoneAuthProvider.verifyPhoneNumber, é necessário fornecer uma instância de OnVerificationStateChangedCallbacks que contenha implementações das funções de retorno de chamada que gerenciam os resultados da solicitação. Por exemplo:

Java
Android

mCallbacks = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {

    @Override
    public void onVerificationCompleted(PhoneAuthCredential credential) {
        // This callback will be invoked in two situations:
        // 1 - Instant verification. In some cases the phone number can be instantly
        //     verified without needing to send or enter a verification code.
        // 2 - Auto-retrieval. On some devices Google Play services can automatically
        //     detect the incoming verification SMS and perform verification without
        //     user action.
        Log.d(TAG, "onVerificationCompleted:" + credential);

        signInWithPhoneAuthCredential(credential);
    }

    @Override
    public void onVerificationFailed(FirebaseException e) {
        // This callback is invoked in an invalid request for verification is made,
        // for instance if the the phone number format is not valid.
        Log.w(TAG, "onVerificationFailed", e);

        if (e instanceof FirebaseAuthInvalidCredentialsException) {
            // Invalid request
            // ...
        } else if (e instanceof FirebaseTooManyRequestsException) {
            // The SMS quota for the project has been exceeded
            // ...
        }

        // Show a message and update the UI
        // ...
    }

    @Override
    public void onCodeSent(String verificationId,
                           PhoneAuthProvider.ForceResendingToken token) {
        // The SMS verification code has been sent to the provided phone number, we
        // now need to ask the user to enter the code and then construct a credential
        // by combining the code with a verification ID.
        Log.d(TAG, "onCodeSent:" + verificationId);

        // Save verification ID and resending token so we can use them later
        mVerificationId = verificationId;
        mResendToken = token;

        // ...
    }
};

Kotlin
Android

callbacks = object : PhoneAuthProvider.OnVerificationStateChangedCallbacks() {

    override fun onVerificationCompleted(credential: PhoneAuthCredential) {
        // This callback will be invoked in two situations:
        // 1 - Instant verification. In some cases the phone number can be instantly
        //     verified without needing to send or enter a verification code.
        // 2 - Auto-retrieval. On some devices Google Play services can automatically
        //     detect the incoming verification SMS and perform verification without
        //     user action.
        Log.d(TAG, "onVerificationCompleted:$credential")

        signInWithPhoneAuthCredential(credential)
    }

    override fun onVerificationFailed(e: FirebaseException) {
        // This callback is invoked in an invalid request for verification is made,
        // for instance if the the phone number format is not valid.
        Log.w(TAG, "onVerificationFailed", e)

        if (e is FirebaseAuthInvalidCredentialsException) {
            // Invalid request
            // ...
        } else if (e is FirebaseTooManyRequestsException) {
            // The SMS quota for the project has been exceeded
            // ...
        }

        // Show a message and update the UI
        // ...
    }

    override fun onCodeSent(
        verificationId: String?,
        token: PhoneAuthProvider.ForceResendingToken
    ) {
        // The SMS verification code has been sent to the provided phone number, we
        // now need to ask the user to enter the code and then construct a credential
        // by combining the code with a verification ID.
        Log.d(TAG, "onCodeSent:" + verificationId!!)

        // Save verification ID and resending token so we can use them later
        storedVerificationId = verificationId
        resendToken = token

        // ...
    }
}

Retornos de chamada de verificação

Na maioria dos apps, os retornos de chamada onVerificationCompleted, onVerificationFailed e onCodeSent são implementados. Dependendo dos requisitos do seu app, também é possível implementar onCodeAutoRetrievalTimeOut.

onVerificationCompleted(PhoneAuthCredential)

Esse método é chamado em duas situações:

  • Verificação instantânea: em alguns casos, o número de telefone pode ser verificado instantaneamente sem que você precise enviar ou inserir um código de verificação.
  • Recuperação automática: em alguns dispositivos, o Google Play Services pode detectar automaticamente o SMS de verificação recebido e executar a verificação sem que nenhuma ação do usuário seja necessária. Esse recurso pode não estar disponível para algumas operadoras.
Em ambos os casos, o número de telefone do usuário foi verificado. Assim, é possível usar o objeto PhoneAuthCredential que é transmitido ao retorno de chamada para fazer o login do usuário.

onVerificationFailed(FirebaseException)

Esse método é chamado em resposta a uma solicitação de verificação inválida, como uma solicitação que especifica um número de telefone ou um código de verificação inválido.

onCodeSent(String verificationId, PhoneAuthProvider.ForceResendingToken)

Opcional. Esse método é chamado depois que o código de verificação é enviado por SMS ao número de telefone fornecido.

Quando esse método é chamado, a maioria dos apps exibe uma IU que solicita que o usuário digite o código de verificação incluso na mensagem SMS. Ao mesmo tempo, a verificação automática pode estar em segundo plano. Depois que o usuário digita o código de verificação, você pode usá-lo com a identificação da verificação que foi passada ao método para criar um objeto PhoneAuthCredential. Depois, use esse objeto para fazer login do usuário. No entanto, alguns apps podem esperar até que onCodeAutoRetrievalTimeOut seja chamado para exibir a IU do código de verificação (não recomendado).

onCodeAutoRetrievalTimeOut(String verificationId)

Opcional. Esse método é chamado depois que a duração do tempo limite especificado para verifyPhoneNumber passa sem acionar onVerificationCompleted antes. Em dispositivos sem cartões SIM, esse método é chamado imediatamente porque não é possível recuperar SMS automaticamente.

Alguns apps bloqueiam a entrada do usuário até que o tempo limite da verificação automática se esgote. Depois disso, eles exibem uma IU que solicita a inserção do código de verificação recebido pelo usuário via mensagem SMS (não recomendado).

Criar um objeto PhoneAuthCredential

Depois que o usuário informar o código de verificação que o Firebase enviou para o telefone dele, crie um objeto PhoneAuthCredential com o código e a identificação da verificação que foram passados para o retorno de chamada onCodeSent ou onCodeAutoRetrievalTimeOut. Quando onVerificationCompleted é chamado, você recebe um objeto PhoneAuthCredential diretamente. Portanto, você pode ignorar esta etapa.

Para criar o objeto PhoneAuthCredential, chame PhoneAuthProvider.getCredential:

Java
Android

PhoneAuthCredential credential = PhoneAuthProvider.getCredential(verificationId, code);

Kotlin
Android

val credential = PhoneAuthProvider.getCredential(verificationId!!, code)

Fazer o login do usuário

Depois de gerar um objeto PhoneAuthCredential no retorno de chamada onVerificationCompleted ou ao chamar PhoneAuthProvider.getCredential, passe o objeto PhoneAuthCredential para FirebaseAuth.signInWithCredential e conclua o fluxo de login:

Java
Android

private void signInWithPhoneAuthCredential(PhoneAuthCredential credential) {
    mAuth.signInWithCredential(credential)
            .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    if (task.isSuccessful()) {
                        // Sign in success, update UI with the signed-in user's information
                        Log.d(TAG, "signInWithCredential:success");

                        FirebaseUser user = task.getResult().getUser();
                        // ...
                    } else {
                        // Sign in failed, display a message and update the UI
                        Log.w(TAG, "signInWithCredential:failure", task.getException());
                        if (task.getException() instanceof FirebaseAuthInvalidCredentialsException) {
                            // The verification code entered was invalid
                        }
                    }
                }
            });
}

Kotlin
Android

private fun signInWithPhoneAuthCredential(credential: PhoneAuthCredential) {
    auth.signInWithCredential(credential)
            .addOnCompleteListener(this) { task ->
                if (task.isSuccessful) {
                    // Sign in success, update UI with the signed-in user's information
                    Log.d(TAG, "signInWithCredential:success")

                    val user = task.result?.user
                    // ...
                } else {
                    // Sign in failed, display a message and update the UI
                    Log.w(TAG, "signInWithCredential:failure", task.exception)
                    if (task.exception is FirebaseAuthInvalidCredentialsException) {
                        // The verification code entered was invalid
                    }
                }
            }
}

Testar com números de telefone na lista de permissões

Use o Console do Firebase para adicionar números de telefone à lista de permissões para o desenvolvimento. Essa ação é vantajosa por estes motivos:

  • A autenticação do número de telefone é feita sem consumir sua cota de uso.
  • A autenticação do número de telefone é feita sem enviar uma mensagem SMS real.
  • Testes consecutivos são executados com o mesmo número de telefone, sem que haja limitação. Isso minimiza o risco de rejeição durante o processo de revisão da App store, caso o revisor use o mesmo número de telefone para teste.
  • O teste em ambientes de desenvolvimento é feito prontamente e sem esforço extra, como a capacidade de desenvolver um simulador do iOS ou um emulador do Android sem o Google Play Services.
  • A gravação de testes de integração é feita sem que haja bloqueio por verificações de segurança, normalmente aplicadas a números de telefone reais em um ambiente de produção.

Os números de telefone da lista de permissões precisam atender aos seguintes requisitos:

  1. Use números fictícios. Não é permitido, pelo Firebase Authentication, a colocação de números de telefones existentes na lista de permissões. Uma opção é usar números com 555 e prefixos, como números de telefone de teste dos EUA, por exemplo: +1 650-555-3434
  2. Os números de telefone precisam estar formatados corretamente para atender a restrições como o tamanho. Eles ainda passarão pela mesma validação dos números de usuários reais.
  3. Você pode adicionar até dez números de telefone para desenvolvimento.
  4. Use números de telefone/códigos de teste difíceis de adivinhar e altere-os com frequência.

Colocar números de telefone e códigos de verificação na lista de permissões

  1. No Console do Firebase, abra a seção Authentication.
  2. Na guia Método de login, ative o provedor de telefone, se ainda não o fez.
  3. Abra o menu suspenso Números de telefone para testes.
  4. Informe o número de telefone que você quer testar, por exemplo: +1 650-555-3434.
  5. Informe o código de verificação de seis dígitos para esse número específico, por exemplo: 654321.
  6. Adicione o número. Se precisar, você pode excluir o número de telefone e o código. Basta passar o cursor sobre a linha correspondente e clicar no ícone da lixeira.

Teste manual

É possível começar a usar um número de telefone da lista de permissões diretamente no aplicativo. Dessa maneira, você pode executar testes manuais durante as etapas de desenvolvimento sem problemas de cotas ou limitações. Também é possível testar diretamente, a partir de um simulador do iOS ou emulador do Android, sem a instalação do Google Play Services.

Quando você informa o número de telefone da lista de permissões e envia o código de verificação, não ocorre o envio de um SMS real. Em vez disso, é necessário informar o código de verificação configurado anteriormente para concluir o login.

Quando o login é concluído, um usuário do Firebase é criado com aquele número de telefone. Este usuário tem o mesmo comportamento e propriedades de um usuário com um número de telefone real e pode acessar o Realtime Database/Cloud Firestore e outros serviços da mesma forma. O token de código gerado durante esse processo tem a mesma assinatura de um usuário com um número de telefone real.

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

Teste de integração

Além do teste manual, o Firebase Authentication conta com APIs para ajudar a escrever testes de integração para o teste de autenticação por telefone. Para desativar a verificação de aplicativos, essas APIs desativam o requisito reCAPTCHA nas notificações push na Web e silenciosas no iOS. Isso possibilita testes de automação nesses fluxos e facilita a implementação. Além disso, fica mais fácil testar os fluxos de verificação instantânea no Android.

No Android, você pode usar prontamente seus números de telefone da lista de permissões sem chamadas de API adicionais. Chamar verifyPhoneNumber com um número da lista de permissões aciona o retorno de chamada onCodeSent, em que você precisará fornecer o código de verificação correspondente. Isso permite testar em emuladores do Android.

Java
Android

String phoneNum = "+16505554567";
String testVerificationCode = "123456";

// Whenever verification is triggered with the whitelisted number,
// provided it is not set for auto-retrieval, onCodeSent will be triggered.
PhoneAuthProvider.getInstance().verifyPhoneNumber(
        phoneNum, 30L /*timeout*/, TimeUnit.SECONDS,
        this, new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {

            @Override
            public void onCodeSent(String verificationId,
                                   PhoneAuthProvider.ForceResendingToken forceResendingToken) {
                // Save the verification id somewhere
                // ...

                // The corresponding whitelisted code above should be used to complete sign-in.
                MainActivity.this.enableUserManuallyInputCode();
            }

            @Override
            public void onVerificationCompleted(PhoneAuthCredential phoneAuthCredential) {
                // Sign in with the credential
                // ...
            }

            @Override
            public void onVerificationFailed(FirebaseException e) {
                 // ...
            }

        });

Kotlin
Android

val phoneNum = "+16505554567"
val testVerificationCode = "123456"

// Whenever verification is triggered with the whitelisted number,
// provided it is not set for auto-retrieval, onCodeSent will be triggered.
PhoneAuthProvider.getInstance().verifyPhoneNumber(
        phoneNum, 30L /*timeout*/, TimeUnit.SECONDS,
        this, object : PhoneAuthProvider.OnVerificationStateChangedCallbacks() {

    override fun onCodeSent(
        verificationId: String?,
        forceResendingToken: PhoneAuthProvider.ForceResendingToken?
    ) {
        // Save the verification id somewhere
        // ...

        // The corresponding whitelisted code above should be used to complete sign-in.
        this@MainActivity.enableUserManuallyInputCode()
    }

    override fun onVerificationCompleted(phoneAuthCredential: PhoneAuthCredential) {
        // Sign in with the credential
        // ...
    }

    override fun onVerificationFailed(e: FirebaseException) {
        // ...
    }
})

Além disso, você pode testar os fluxos de recuperação automática no Android definindo o número da lista de permissões e seu código de verificação correspondente para a recuperação automática chamando setAutoRetrievedSmsCodeForPhoneNumber.

Quando verifyPhoneNumber é chamado, ele aciona onVerificationCompleted com o PhoneAuthCredential diretamente. Isso funciona apenas com números de telefone na lista de permissões.

Verifique se ele está desativado e se nenhum número de telefone na lista de permissões está codificado ao publicar seu aplicativo na Google Play Store.

Java
Android

// The test phone number and code should be whitelisted in the console.
String phoneNumber = "+16505554567";
String smsCode = "123456";

FirebaseAuth firebaseAuth = FirebaseAuth.getInstance();
FirebaseAuthSettings firebaseAuthSettings = firebaseAuth.getFirebaseAuthSettings();

// Configure faking the auto-retrieval with the whitelisted numbers.
firebaseAuthSettings.setAutoRetrievedSmsCodeForPhoneNumber(phoneNumber, smsCode);

PhoneAuthProvider phoneAuthProvider = PhoneAuthProvider.getInstance();
phoneAuthProvider.verifyPhoneNumber(
        phoneNumber,
        60L,
        TimeUnit.SECONDS,
        this, /* activity */
        new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
            @Override
            public void onVerificationCompleted(PhoneAuthCredential credential) {
                // Instant verification is applied and a credential is directly returned.
                // ...
            }

            // ...
        });

Kotlin
Android

// The test phone number and code should be whitelisted in the console.
val phoneNumber = "+16505554567"
val smsCode = "123456"

val firebaseAuth = FirebaseAuth.getInstance()
val firebaseAuthSettings = firebaseAuth.firebaseAuthSettings

// Configure faking the auto-retrieval with the whitelisted numbers.
firebaseAuthSettings.setAutoRetrievedSmsCodeForPhoneNumber(phoneNumber, smsCode)

val phoneAuthProvider = PhoneAuthProvider.getInstance()
phoneAuthProvider.verifyPhoneNumber(
        phoneNumber,
        60L,
        TimeUnit.SECONDS,
        this, /* activity */
        object : PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
            override fun onVerificationCompleted(credential: PhoneAuthCredential) {
                // Instant verification is applied and a credential is directly returned.
                // ...
            }

            // ...
        })

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 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, é possível acessar informações básicas de perfil do usuário por meio do objeto FirebaseUser. 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:

Java
Android

FirebaseAuth.getInstance().signOut();

Kotlin
Android

FirebaseAuth.getInstance().signOut()