Verificar números de telefone na Web com a API WebOTP

Ajudar os usuários com OTPs recebidos por SMS

O que é a API WebOTP?

Atualmente, a maioria das pessoas no mundo tem um dispositivo móvel, e os desenvolvedores geralmente usam números de telefone como identificador dos usuários dos serviços.

Há várias maneiras de verificar números de telefone, mas uma senha única (OTP, na sigla em inglês) gerada aleatoriamente e enviada por SMS é uma das mais comuns. O envio desse código de volta ao servidor do desenvolvedor demonstra o controle do número de telefone.

Essa ideia já foi implantada em vários cenários para:

  • Número de telefone como um identificador do usuário. Ao se inscrever em um novo serviço, alguns sites solicitam um número de telefone em vez de um endereço de e-mail e o usam como um identificador de conta.
  • Verificação em duas etapas. Ao fazer login, um site solicita um código de uso único enviado por SMS, além de uma senha ou outro fator de conhecimento para maior segurança.
  • Confirmação do pagamento. Quando um usuário está fazendo um pagamento, pedir um código de uso único enviado por SMS pode ajudar a verificar a intenção da pessoa.

O processo atual cria atrito para os usuários. Encontrar um OTP em uma mensagem de SMS e copiá-lo e colá-lo no formulário é complicado, reduzindo as taxas de conversão em jornadas de usuários importantes. A simplificação desse processo é uma solicitação antiga da Web feita por muitos dos maiores desenvolvedores do mundo. O Android tem uma API que faz exatamente isso. O iOS e o Safari também.

A API WebOTP permite que seu app receba mensagens formatadas de maneira especial vinculadas ao domínio do app. Com isso, você pode receber uma OTP de uma mensagem SMS e verificar um número de telefone do usuário com mais facilidade.

Confira na prática

Digamos que um usuário queira verificar o número de telefone em um site. O site envia uma mensagem de texto ao usuário por SMS, e o usuário insere a OTP da mensagem para verificar a propriedade do número de telefone.

Com a API WebOTP, essas etapas são tão fáceis quanto um toque para o usuário, conforme demonstrado no vídeo. Quando a mensagem de texto chega, uma página inferior aparece e solicita que o usuário verifique o número de telefone. Depois de clicar no botão Verificar na página inferior, o navegador cola o OTP no formulário, e o formulário é enviado sem que o usuário precise pressionar Continuar.

O processo todo está diagramado na imagem abaixo.

Diagrama da API WebOTP

Teste a demonstração. Ele não solicita seu número de telefone nem envia um SMS para seu dispositivo, mas você pode enviar um de outro dispositivo copiando o texto exibido na demonstração. Isso funciona porque não importa quem é o remetente ao usar a API WebOTP.

  1. Acesse https://web-otp.glitch.me no Chrome 84 ou mais recente em um dispositivo Android.
  2. Envie a seguinte mensagem de texto SMS do outro smartphone para o seu.
Your OTP is: 123456.

@web-otp.glitch.me #12345

Você recebeu o SMS e viu a solicitação para inserir o código na área de entrada? É assim que a API WebOTP funciona para os usuários.

O uso da API WebOTP consiste em três partes:

  • Uma tag <input> devidamente anotada
  • JavaScript no seu app da Web
  • Texto da mensagem formatada enviada por SMS.

Vou falar primeiro sobre a tag <input>.

Anotar uma tag <input>

O WebOTP funciona sem nenhuma anotação HTML, mas, para compatibilidade entre navegadores, é altamente recomendável adicionar autocomplete="one-time-code" à tag <input> em que você espera que o usuário insira um OTP.

Isso permite que o Safari 14 ou mais recente sugira que o usuário preencha automaticamente o campo <input> com um OTP quando receber um SMS com o formato descrito em Formatar a mensagem SMS, mesmo que não ofereça suporte ao WebOTP.

HTML

<form>
  <input autocomplete="one-time-code" required/>
  <input type="submit">
</form>

Usar a API WebOTP

Como o WebOTP é simples, basta copiar e colar o código abaixo. Vou explicar o que está acontecendo.

JavaScript

if ('OTPCredential' in window) {
  window.addEventListener('DOMContentLoaded', e => {
    const input = document.querySelector('input[autocomplete="one-time-code"]');
    if (!input) return;
    const ac = new AbortController();
    const form = input.closest('form');
    if (form) {
      form.addEventListener('submit', e => {
        ac.abort();
      });
    }
    navigator.credentials.get({
      otp: { transport:['sms'] },
      signal: ac.signal
    }).then(otp => {
      input.value = otp.code;
      if (form) form.submit();
    }).catch(err => {
      console.log(err);
    });
  });
}

Detecção de recursos

A detecção de recursos é a mesma de muitas outras APIs. A escuta do evento DOMContentLoaded vai aguardar a árvore DOM ficar pronta para consulta.

JavaScript

if ('OTPCredential' in window) {
  window.addEventListener('DOMContentLoaded', e => {
    const input = document.querySelector('input[autocomplete="one-time-code"]');
    if (!input) return;
    …
    const form = input.closest('form');
    …
  });
}

Processar a OTP

A API WebOTP é bastante simples. Use navigator.credentials.get() para receber o OTP. O WebOTP adiciona uma nova opção otp a esse método. Ele tem apenas uma propriedade: transport, cujo valor precisa ser uma matriz com a string 'sms'.

JavaScript

    …
    navigator.credentials.get({
      otp: { transport:['sms'] }
      …
    }).then(otp => {
    …

Isso aciona o fluxo de permissão do navegador quando uma mensagem SMS chega. Se a permissão for concedida, a promessa retornada será resolvida com um objeto OTPCredential.

Conteúdo do objeto OTPCredential recebido

{
  code: "123456" // Obtained OTP
  type: "otp"  // `type` is always "otp"
}

Em seguida, transmita o valor do OTP para o campo <input>. O envio direto do formulário elimina a etapa em que o usuário precisa tocar em um botão.

JavaScript

    …
    navigator.credentials.get({
      otp: { transport:['sms'] }
      …
    }).then(otp => {
      input.value = otp.code;
      if (form) form.submit();
    }).catch(err => {
      console.error(err);
    });
    …

Como abortar a mensagem

Caso o usuário insira manualmente um OTP e envie o formulário, você pode cancelar a chamada get() usando uma instância AbortController no objeto options.

JavaScript

    …
    const ac = new AbortController();
    …
    if (form) {
      form.addEventListener('submit', e => {
        ac.abort();
      });
    }
    …
    navigator.credentials.get({
      otp: { transport:['sms'] },
      signal: ac.signal
    }).then(otp => {
    …

Formatar a mensagem de SMS

A API parece bastante simples, mas há algumas coisas que você precisa saber antes de usá-la. A mensagem precisa ser enviada depois que navigator.credentials.get() for chamada e precisa ser recebida no dispositivo em que get() foi chamado. Por fim, a mensagem precisa seguir a seguinte formatação:

  • A mensagem começa com um texto legível por humanos (opcional) que contém uma string alfanumérica de quatro a dez caracteres com pelo menos um número, deixando a última linha para o URL e o OTP.
  • A parte do domínio do URL do site que invocou a API precisa ser precedida por @.
  • O URL precisa conter um cifrão ("#") seguido pelo OTP.

Exemplo:

Your OTP is: 123456.

@www.example.com #123456

Confira alguns exemplos ruins:

Exemplo de texto de SMS com formato incorreto Por que isso não funciona
Here is your code for @example.com #123456 @ deve ser o primeiro caractere da última linha.
Your code for @example.com is #123456 @ deve ser o primeiro caractere da última linha.
Your verification code is 123456

@example.com\t#123456
Um único espaço é esperado entre @host e #code.
Your verification code is 123456

@example.com  #123456
Um único espaço é esperado entre @host e #code.
Your verification code is 123456

@ftp://example.com #123456
O esquema de URL não pode ser incluído.
Your verification code is 123456

@https://example.com #123456
O esquema de URL não pode ser incluído.
Your verification code is 123456

@example.com:8080 #123456
Não é possível incluir a porta.
Your verification code is 123456

@example.com/foobar #123456
O caminho não pode ser incluído.
Your verification code is 123456

@example .com #123456
Não há espaços em branco no domínio.
Your verification code is 123456

@domain-forbiden-chars-#%/:<>?@[] #123456
Não há caracteres proibidos no domínio.
@example.com #123456

Mambo Jumbo
@host e #code devem ser a última linha.
@example.com #123456

App hash #oudf08lkjsdf834
@host e #code devem ser a última linha.
Your verification code is 123456

@example.com 123456
# ausente.
Your verification code is 123456

example.com #123456
@ ausente.
Hi mom, did you receive my last text @ e # ausentes.

Demonstrações

Teste várias mensagens com a demonstração: https://web-otp.glitch.me

Você também pode bifurcar e criar sua versão: https://glitch.com/edit/#!/web-otp.

Usar o WebOTP em um iframe entre origens

A inserção de um OTP por SMS em um iframe de origem cruzada é normalmente usada para confirmação de pagamento, especialmente com o 3D Secure. Com o formato comum para oferecer suporte a iframes de origem cruzada, a API WebOTP envia OTPs vinculados a origens aninhadas. Por exemplo:

  • Um usuário visita shop.example para comprar um par de sapatos com um cartão de crédito.
  • Depois de inserir o número do cartão de crédito, o provedor de pagamento integrado mostra um formulário de bank.example em um iframe pedindo que o usuário verifique o número de telefone para finalizar a compra rapidamente.
  • O bank.example envia um SMS que contém um OTP para que o usuário possa digitá-lo para verificar a identidade.

Para usar a API WebOTP em um iframe de origem cruzada, você precisa fazer duas coisas:

  • Faça anotações sobre a origem do frame superior e a origem do iframe na mensagem de texto do SMS.
  • Configure a política de permissões para permitir que o iframe entre origens receba OTP diretamente do usuário.
API WebOTP em um iframe em ação.

Teste a demonstração em https://web-otp-iframe-demo.stackblitz.io.

Anotar origens vinculadas à mensagem de texto do SMS

Quando a API WebOTP é chamada em um iframe, a mensagem de texto SMS precisa incluir a origem do frame superior precedida por @, seguida pelo OTP precedido por # e a origem do iframe precedida por @ na última linha.

Your verification code is 123456

@shop.example #123456 @bank.exmple

Configurar a política de permissões

Para usar o WebOTP em um iframe entre origens, o incorporador precisa conceder acesso a essa API pela política de permissões de credenciais de otp para evitar comportamento inesperado. Em geral, há duas maneiras de alcançar esse objetivo:

Por cabeçalho HTTP:

Permissions-Policy: otp-credentials=(self "https://bank.example")

pelo atributo allow do iframe:

<iframe src="https://bank.example/…" allow="otp-credentials"></iframe>

Confira mais exemplos sobre como especificar uma política de permissão .

Usar o WebOTP no computador

No Chrome, o WebOTP oferece suporte à detecção de SMSs recebidos em outros dispositivos para ajudar os usuários a concluir a verificação do número de telefone no computador.

API WebOTP no computador.

Esse recurso exige que o usuário faça login na mesma Conta do Google no Chrome para computador e no Chrome para Android.

Tudo o que os desenvolvedores precisam fazer é implementar a API WebOTP no site para computador, da mesma forma que fazem no site para dispositivos móveis, mas sem truques especiais.

Saiba mais em Verificar um número de telefone no computador usando a API WebOTP.

Perguntas frequentes

A caixa de diálogo não aparece, embora eu esteja enviando uma mensagem formatada corretamente. O que deu errado?

Há algumas ressalvas ao testar a API:

  • Se o número de telefone do remetente estiver incluído na lista de contatos do destinatário, essa API não será acionada devido ao design da API SMS User Consent (consentimento do usuário do SMS, em inglês) subjacente.
  • Se você estiver usando um perfil de trabalho no dispositivo Android e o WebOTP não funcionar, tente instalar e usar o Chrome no seu perfil pessoal (ou seja, o mesmo perfil em que você recebe mensagens SMS).

Verifique o formato para saber se o SMS está formatado corretamente.

Essa API é compatível com diferentes navegadores?

O Chromium e o WebKit concordaram com o formato de mensagem de texto SMS, e a Apple anunciou o suporte do Safari a partir do iOS 14 e do macOS Big Sur. Embora o Safari não ofereça suporte à API JavaScript WebOTP, ao anotar o elemento input com autocomplete=["one-time-code"], o teclado padrão sugere automaticamente que você insira o OTP se a mensagem SMS estiver em conformidade com o formato.

É seguro usar o SMS como uma forma de autenticação?

Embora o OTP por SMS seja útil para verificar um número de telefone quando ele é fornecido pela primeira vez, a verificação de número de telefone por SMS precisa ser usada com cuidado para a re-autenticação, já que os números de telefone podem ser roubados e reciclados pelas operadoras. O WebOTP é um mecanismo conveniente de reautorização e recuperação, mas os serviços precisam combinar isso com outros fatores, como um desafio de conhecimento, ou usar a API Web Authentication para uma autenticação forte.

Onde posso informar bugs na implementação do Chrome?

Você encontrou um bug na implementação do Chrome?

  • Registre um bug em crbug.com. Inclua o máximo de detalhes possível, instruções simples para reprodução e defina Components como Blink>WebOTP.

Como posso ajudar esse recurso?

Você planeja usar a API WebOTP? Seu apoio público nos ajuda a priorizar os recursos e mostra a outros fornecedores de navegadores a importância de oferecer suporte a eles. Envie um tweet para @ChromiumDev usando a hashtag #WebOTP e nos informe onde e como você está usando.

Recursos