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

Ajudar usuários com OTPs recebidas por SMS

Eiji Kitamura
Eiji Kitamura

O que é a API WebOTP?

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

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

Essa ideia já foi adotada em diversos cenários a serem alcançados:

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

O processo atual cria atrito para os usuários. Encontrar uma OTP dentro de uma mensagem SMS, depois copiar e colar no formulário é complicado, reduzindo as taxas de conversão em jornadas ideais do usuário. Simplificar isso tem sido um pedido de longa data para a Web de muitos dos maiores desenvolvedores globais. O Android tem uma API que faz exatamente isso. O mesmo acontece com o iOS e o Safari.

A API WebOTP permite que o app receba mensagens com formatação especial vinculadas ao domínio do app. Você pode conseguir uma OTP de maneira programática usando uma mensagem SMS e verificar um número de telefone para o usuário com mais facilidade.

Confira na prática

Digamos que um usuário queira confirmar 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 simples com 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 a OTP no formulário, que é enviado sem que o usuário precise pressionar Continuar.

Todo o processo está diagramado na imagem abaixo.

Diagrama da API WebOTP

Teste a demonstração por conta própria. Ele não solicita seu número de telefone nem envia um SMS para o dispositivo, mas é possível 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 posterior em um dispositivo Android.
  2. Envie ao seu smartphone a seguinte mensagem de texto SMS de outro smartphone.
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> anotada corretamente
  • JavaScript no seu app da Web
  • Texto de mensagem formatado enviado por SMS.

Vou abordar a tag <input> primeiro.

Anotar uma tag <input>

A WebOTP funciona sem anotações HTML. No entanto, para compatibilidade entre navegadores, recomendamos adicionar autocomplete="one-time-code" à tag <input>, onde você espera que o usuário insira uma OTP.

Isso permite que o Safari 14 ou mais recente sugira que o usuário preencha automaticamente o campo <input> com uma OTP ao receber um SMS com o formato descrito em Formatar a mensagem SMS, mesmo que ele não tenha suporte a 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 a seguir para que ele funcione. 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 é igual à de muitas outras APIs. Ouvir o evento DOMContentLoaded aguardará a árvore DOM ficar pronta para a 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 em si é bastante simples. Use navigator.credentials.get() para conseguir a OTP. O WebOTP adiciona uma nova opção otp a esse método. Ela 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ões do navegador quando uma mensagem SMS chega. Se a permissão for concedida, a promessa retornada vai 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 da OTP ao campo <input>. O envio direto do formulário elimina a etapa que exige que o usuário toque 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 cancelar a mensagem

Caso o usuário insira manualmente uma 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 SMS

A API em si pode parecer simples o suficiente, mas há algumas coisas que você precisa saber antes de usá-la. A mensagem precisa ser enviada depois que navigator.credentials.get() é chamado e recebida no dispositivo em que get() foi chamado. Por fim, a mensagem precisa aderir à seguinte formatação:

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

Exemplo:

Your OTP is: 123456.

@www.example.com #123456

Confira alguns exemplos ruins:

Exemplo de texto SMS incorreto Por que isso não funciona?
Here is your code for @example.com #123456 Espera-se que @ seja o primeiro caractere da última linha.
Your code for @example.com is #123456 Espera-se que @ seja o primeiro caractere da última linha.
Your verification code is 123456

@example.com\t#123456
Espera-se um único espaço entre @host e #code.
Your verification code is 123456

@example.com  #123456
Espera-se um único espaço 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
A porta não pode ser incluída.
Your verification code is 123456

@example.com/foobar #123456
Não é possível incluir o caminho.
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
Nenhum caractere proibido no domínio.
@example.com #123456

Mambo Jumbo
Espera-se que @host e #code sejam a última linha.
@example.com #123456

App hash #oudf08lkjsdf834
Espera-se que @host e #code sejam 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 (em inglês)

Também é possível bifurcá-la e criar sua versão: https://glitch.com/edit/#!/web-otp.

Usar WebOTP em um iframe de origem cruzada

A inserção de uma OTP por SMS em um iframe de origem cruzada geralmente é 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 fornece OTPs vinculadas a origens aninhadas. 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 solicitando que o usuário verifique o número de telefone para agilizar a finalização da compra.
  • bank.example envia ao usuário um SMS com uma OTP para que ele possa inseri-la e verificar a identidade.

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

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

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

Anotar origens limitadas na mensagem de texto SMS

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

Your verification code is 123456

@shop.example #123456 @bank.exmple

Configurar política de permissões

Para usar WebOTP em um iframe de origem cruzada, o incorporador precisa conceder acesso a essa API por meio da política de permissões otp-credentials para evitar comportamentos indesejados. Em geral, existem duas maneiras de alcançar essa meta:

via cabeçalho HTTP:

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

por meio do atributo allow do iframe:

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

Veja mais exemplos sobre como especificar uma política de permissões .

Usar o WebOTP no computador

No Chrome, o WebOTP é compatível com a 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.

Para usar esse recurso, o usuário precisa fazer login na mesma Conta do Google no Chrome para computador e no Android.

Tudo o que os desenvolvedores precisam fazer é implementar a API WebOTP no site para computador, da mesma maneira que fazem no site móvel, mas nenhum truque especial é necessário.

Saiba mais detalhes 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 vai ser acionada devido ao design da API SMS User Consent.
  • Se você estiver usando um perfil de trabalho no dispositivo Android e o WebOTP não funcionar, tente instalar e usar o Chrome no perfil pessoal, ou seja, o mesmo perfil em que você recebe mensagens SMS.

Verifique novamente no formato se seu SMS está formatado corretamente.

Esta 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 WebOTP JavaScript, ao anotar o elemento input com autocomplete=["one-time-code"], o teclado padrão sugere automaticamente que você insira a OTP se a mensagem SMS estiver em conformidade com o formato.

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

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

Onde informo bugs na implementação do Chrome?

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

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

Como posso usar esse recurso?

Você pretende usar a API WebOTP? Seu suporte público nos ajuda a priorizar recursos e mostra a outros fornecedores de navegadores como é fundamental oferecer suporte a eles. Envie um tweet para @ChromiumDev usando a hashtag #WebOTP e informe onde e como ela está sendo usada.

Recursos