Práticas recomendadas para formulários de OTP por SMS

Saiba como otimizar seu formulário de OTP por SMS e melhorar a experiência do usuário.

Pedir que um usuário forneça a senha única (OTP) enviada por SMS é uma maneira comum de confirmar o número de telefone de um usuário. Há alguns casos de uso para OTP por SMS:

  • Autenticação de dois fatores. Além do nome de usuário e da senha, o SMS OTP pode ser usado como um indicador forte de que a conta pertence à pessoa que recebeu o SMS OTP.
  • Verificação do número de telefone. Alguns serviços usam um número de telefone como o identificador principal do usuário. Nesses serviços, os usuários podem inserir o número de telefone e o OTP recebido por SMS para provar a identidade. Às vezes, ela é combinada com um PIN para constituir uma autenticação de dois fatores.
  • Recuperação de conta. Quando um usuário perde o acesso à conta, é necessário haver uma maneira de recuperá-la. Enviar um e-mail para o endereço de e-mail registrado ou um SMS OTP para o número de telefone são métodos comuns de recuperação de conta.
  • Confirmação de pagamento: em sistemas de pagamento, alguns bancos ou emissores de cartão de crédito solicitam uma autenticação adicional do pagador por motivos de segurança. O SMS OTP é comumente usado para esse fim.

Esta postagem explica as práticas recomendadas para criar um formulário de OTP por SMS para os casos de uso acima.

Lista de verificação

Para oferecer a melhor experiência do usuário com o OTP por SMS, siga estas etapas:

  • Use o elemento <input> com:
    • type="text"
    • inputmode="numeric"
    • autocomplete="one-time-code"
  • Use @BOUND_DOMAIN #OTP_CODE como a última linha da mensagem SMS de OTP.
  • Use a API WebOTP.

Use o elemento <input>

Usar um formulário com um elemento <input> é a prática recomendada mais importante que você pode seguir, porque funciona em todos os navegadores. Mesmo que outras sugestões desta postagem não funcionem em alguns navegadores, o usuário ainda poderá inserir e enviar o OTP manualmente.

<form action="/verify-otp" method="POST">
  <input type="text"
         inputmode="numeric"
         autocomplete="one-time-code"
         pattern="\d{6}"
         required>
</form>

Confira a seguir algumas ideias para garantir que um campo de entrada aproveite ao máximo a funcionalidade do navegador.

type="text"

Como os OTPs geralmente são números de cinco ou seis dígitos, o uso de type="number" em um campo de entrada pode parecer intuitivo, porque muda o teclado do dispositivo móvel para números apenas. Isso não é recomendado porque o navegador espera que um campo de entrada seja um número contável, e não uma sequência de vários números, o que pode causar um comportamento inesperado. O uso de type="number" faz com que os botões para cima e para baixo sejam exibidos ao lado do campo de entrada. Ao pressionar esses botões, o número é aumentado ou diminuído e os zeros anteriores podem ser removidos.

Use type="text". Isso não vai transformar o teclado do dispositivo móvel em números somente, mas tudo bem, porque a próxima dica para usar inputmode="numeric" faz isso.

inputmode="numeric"

Use inputmode="numeric" para mudar o teclado do dispositivo móvel para números apenas.

Alguns sites usam type="tel" para campos de entrada de OTP, porque ele também transforma o teclado do dispositivo móvel em números apenas (incluindo * e #) quando em foco. Esse hack foi usado no passado quando o inputmode="numeric" não tinha suporte amplo. Como o Firefox começou a oferecer suporte a inputmode="numeric", não é necessário usar o hack type="tel" semanticamente incorreto.

autocomplete="one-time-code"

O atributo autocomplete permite que os desenvolvedores especifiquem qual permissão o navegador tem para fornecer assistência de preenchimento automático e informa o navegador sobre o tipo de informação esperado no campo.

Com autocomplete="one-time-code", sempre que um usuário receber uma mensagem SMS enquanto um formulário estiver aberto, o sistema operacional vai analisar o OTP no SMS de forma heurística e o teclado vai sugerir que o usuário insira o OTP. Ele funciona apenas no Safari 12 e versões mais recentes no iOS, iPadOS e macOS, mas recomendamos que você o use, porque é uma maneira fácil de melhorar a experiência de OTP por SMS nessas plataformas.

`autocomplete="one-time-code"` em ação.

O autocomplete="one-time-code" melhora a experiência do usuário, mas você pode fazer mais garantindo que a mensagem SMS esteja em conformidade com o formato de mensagem de origem.

Formatar o texto do SMS

Melhore a experiência do usuário ao inserir um OTP alinhando-se à especificação de códigos de uso único vinculados à origem enviados por SMS.

A regra de formato é simples: termine a mensagem SMS com o domínio do destinatário precedido por @ e o OTP precedido por #.

Exemplo:

Your OTP is 123456

@web-otp.glitch.me #123456

Usar um formato padrão para mensagens de OTP facilita a extração de códigos delas e torna o processo mais confiável. A associação de códigos OTP a sites dificulta que os usuários sejam enganados para fornecer um código a sites maliciosos.

O uso desse formato oferece alguns benefícios:

  • O OTP será vinculado ao domínio. Se o usuário estiver em domínios diferentes do especificado na mensagem SMS, a sugestão de OTP não vai aparecer. Isso também reduz o risco de ataques de phishing e possíveis invasões de contas.
  • O navegador agora poderá extrair o OTP de forma confiável sem depender de heurísticas misteriosas e instáveis.

Quando um site usa autocomplete="one-time-code", o Safari com iOS 14 ou mais recente sugere o OTP seguindo as regras acima.

Esse formato de mensagem de SMS também beneficia outros navegadores além do Safari. O Chrome, o Opera e o Vivaldi no Android também oferecem suporte à regra de códigos de uso único com limite de origem com a API WebOTP, mas não por meio de autocomplete="one-time-code".

Usar a API WebOTP

A API WebOTP (link em inglês) dá acesso ao OTP recebido em uma mensagem SMS. Ao chamar navigator.credentials.get() com o tipo otp (OTPCredential), em que transport inclui sms, o site vai aguardar que um SMS que obedece aos códigos de uso único vinculados à origem seja enviado e que o acesso seja concedido pelo usuário. Depois que o OTP é transmitido para o JavaScript, o site pode usá-lo em um formulário ou fazer POST diretamente para o servidor.

navigator.credentials.get({
  otp: {transport:['sms']}
})
.then(otp => input.value = otp.code);
API WebOTP em ação.

Saiba como usar a API WebOTP em detalhes em Verificar números de telefone na Web com a API WebOTP ou copie e cole o snippet abaixo. Verifique se o elemento <form> tem um atributo action e method definido corretamente.

// Feature detection
if ('OTPCredential' in window) {
  window.addEventListener('DOMContentLoaded', e => {
    const input = document.querySelector('input[autocomplete="one-time-code"]');
    if (!input) return;
    // Cancel the WebOTP API if the form is submitted manually.
    const ac = new AbortController();
    const form = input.closest('form');
    if (form) {
      form.addEventListener('submit', e => {
        // Cancel the WebOTP API.
        ac.abort();
      });
    }
    // Invoke the WebOTP API
    navigator.credentials.get({
      otp: { transport:['sms'] },
      signal: ac.signal
    }).then(otp => {
      input.value = otp.code;
      // Automatically submit the form when an OTP is obtained.
      if (form) form.submit();
    }).catch(err => {
      console.log(err);
    });
  });
}

Foto de Jason Leung no Unsplash.