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 OTP por SMS é usado com frequência para essa finalidade.

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.

Usar 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 somente (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 senha única 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 o iOS 14 ou versões mais recentes 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 vinculados à origem com a API WebOTP, mas não por 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.