Verificação de contas por SMS utilizando a SMS Retriever API
Em outubro de 2018, a Google anunciou atualizações para melhorar a privacidade de usuários Android que limitam o uso das permissões dos grupos Call Log e SMS. Permissões desses grupos permitem os desenvolvedores a gerenciar chamadas do telefone, ler e escrever SMS, entre outras coisas.
Desde 9 de Janeiro de 2019, apenas aplicativos aprovados que tem como funcionalidade principal gerenciar SMS ou chamadas de telefone poderão utilizá-los. Mesmo assim, os dados recuperados não poderão ser vendidos, transferidos ou utilizados a fim de marketing. A partir de agora, quase todos os aplicativos que declaram alguma das permissões que pertencem a esses grupos no Manifest precisarão ser atualizados para as removerem ou migrarem para uma implementação alternativa.
Um uso comum das permissões RECEIVE_SMS e READ_SMS é para realizar o One Time Password e realizar verificações de conta por SMS (Account Verification). O uso dessas permissões com esses propósitos não são seguros e podem expor dados do usuário. Porém, existem alternativas mais seguras.
Uma delas, é o uso da SMS Retriever API.
SMS Retriever API
Com a SMS Retriever API, é possível verificar contas sem requerer que o usuário digite o código de verificação e sem precisar utilizar algum tipo de permissão.
Isso pode ser realizado em poucos passos, que requerem implementação server-side e client-side. Para manter esse artigo breve, apenas a implementação client-side será abordada.
Implementando a verificação por SMS
Como mencionado anteriormente, a implementação do backend não será abordada neste artigo. Mas uma coisa importante para se manter em mente é que a mensagem de SMS enviada do servidor deve possuir uma estrutura específica.
Estrutura de mensagem SMS
A mensagem de SMS deve começar com um dos seguintes prefixos:
- <#>
- \u200b\u200b
O primeiro é visível e apenas aparecerá no conteúdo da mensagem. O último é um código unicode invisível, porém requer que a mensagem tenha suporte a unicode.
A mensagem precisa terminar com uma string derivada do nome do pacote do aplicativo, de seu certificado e precisa possuir no máximo 140 bytes.
<#> Seu código é: 401947
FA+9qCX9VSu
A hash no final da mensagem é feita do nome do pacote do aplicativo e da chave pública de seu certificado. Uma das maneiras de gerar esse código hash é rodando o seguinte comando:
keytool -exportcert -alias AliasDaMinhaKeyStore -keystore MinhasChaves.keystore | xxd -p | tr -d "[:space:]" | echo -n com.exemplo.meuapp `cat` | sha256sum | tr -d "[:space:]-" | xxd -r -p | base64 | cut -c1-11
Certifique-se de que AliasDaMinhaKeyStore seja substituída com o alias da KeyStore do aplicativo, MinhasChaves.keystore com sua KeyStore e com.exemplo.meuapp com o nome do pacote do aplicativo.
Observações:
- Se estiver utilizando o aplicativo em modo debug, você deve assinar a apk de debug e extrair o certificado da KeyStore utilizada (Mais detalhes aqui).
- Se estiver utilizando um Mac OS, será necessário instalar o coreutils para que os comandos sha256sum ou gsha256sum possam ser utilizados.
Pré requisitos
A dependência da SMS Retriever API está disponível apenas em dispositivos com o Play Services na versão 10.2 ou mais recente.
Dependências
A dependência da SMS Retriever API deve ser adicionada ao build.gradle:
Iniciando o SMS Retriever
Depois de pegar o número do telefone do usuário, é necessário criar uma instância da classe SmsRetrieverClient, inicializar o retriever e adicionar um listener para sucessos e falhas.
O método startSmsRetriever espera pela mensagem SMS com um timeout de 5 minutos. A mensagem SMS designada ao aplicativo será recebida via Broadcast com a ação SMS_RETRIEVED_ACTION.
O código do BroadcastReceiver que espera pelo SMS será parecido com o seguinte:
O BroadcastReceiver deve ser registrado no Manifest.
Depois de extrair o código, o aplicativo deve enviar o código extraído ao servidor para que ele possa completar a verificação da conta.
Um código de exemplo completo da SMS Retriever API pode ser encontrado aqui:
https://github.com/wilder/SmsRetrieverApiExample