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

Ajudar usuários com OTPs recebidas 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 um identificador dos usuários dos serviços.

Há várias maneiras de verificar números de telefone, mas uma senha única (OTP) gerada aleatoriamente, 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 implementada em muitos cenários para atingir:

  • 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 solicita um código único enviado por SMS sobre uma senha ou outro fator de conhecimento para segurança extra.
  • Confirmação do pagamento. Quando um usuário estiver 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 uma OTP em uma mensagem SMS e, em seguida, copiar e colar no formulário é complicado, reduzindo as taxas de conversão em jornadas ideais do usuário. Simplificar isso é uma solicitação de muitos dos maiores desenvolvedores globais para a Web. 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 especialmente formatadas e vinculadas ao domínio do app. Assim, você pode conseguir uma OTP de maneira programática por 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 verificar um 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.

A imagem abaixo mostra todo o processo.

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 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 posterior em um dispositivo Android.
  2. Envie ao seu smartphone a seguinte mensagem de texto SMS de outro telefone.
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 formatado de mensagem enviado por SMS.

Falarei sobre a tag <input> primeiro.

Anotar uma tag <input>

A WebOTP funciona sem nenhuma anotação HTML, mas, 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 versões mais recentes sugiram 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 ofereça suporte à 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 ajudar você a entender 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 atributos é igual à de muitas outras APIs. Detectar o evento DOMContentLoaded aguardará a árvore do 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. 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 da OTP para o 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);
    });
    …

Cancelando 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 é bem simples, 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) que contém uma string alfanumérica de quatro a dez caracteres com pelo menos um número na última linha do URL e da 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

Veja 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
É esperado um único espaço entre @host e #code.
Your verification code is 123456

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

@ftp://example.com #123456
Não é possível incluir o esquema do URL.
Your verification code is 123456

@https://example.com #123456
Não é possível incluir o esquema do URL.
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
Nenhum espaço 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
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 # não foram informados.

Demonstrações

Teste várias mensagens com a demonstração: https://web-otp.glitch.me (link em inglês)

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

Usar WebOTP de um iframe de origem cruzada

A inserção de uma OTP por SMS para 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 oferece 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.
  • O bank.example envia um SMS que contém uma OTP ao usuário para que ele possa digitá-la e verificar a identidade.

Para usar a API WebOTP a partir de 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 (em inglês).

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 pela OTP precedida 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 a 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 atingir essa meta:

por 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>

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

Usar o WebOTP no computador

No Chrome, o WebOTP permite detectar mensagens SMS recebidas 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 forma que fazem no site para dispositivos móveis, mas não são necessários 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.
  • 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 novamente o formato para ver 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 ele 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 sugerirá 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 é fornecido pela primeira vez, a verificação do número de telefone por SMS precisa ser usada com cuidado para fazer a autenticação, já que os números de telefone 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?

  • Registre 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 ajudar com esse recurso?

Você planeja usar a API WebOTP? Seu suporte público nos ajuda a priorizar recursos e mostra a outros fornecedores de navegador como é importante oferecer suporte a eles. Envie um tweet para @ChromiumDev com a hashtag #WebOTP e conte para a gente onde e como você está usando a hashtag.

Recursos