Skip to main content
Ao final, seu backend em Node envia um código de login (OTP) pelo WhatsApp e valida o que o usuário digitou, com expiração de 5 minutos, limite de 5 tentativas e reenvio controlado. A Arara entrega a mensagem. Gerar, guardar e validar o código é do seu backend.

Antes de começar

  • Chave de API na variável ARARA_API_KEY. Ver Autenticação.
  • Número conectado na organização. Ver Números.
  • Template da categoria AUTHENTICATION aprovado (o passo 1 cria). Ver Templates.
  • Node 18 ou mais novo e "type": "module" no package.json.
  • Um segredo aleatório em OTP_SECRET, usado para o hash do código (openssl rand -hex 32).
A Meta só libera template de autenticação para empresa verificada, com o número no limite de 2.000 conversas ou mais e sem restrição. Sem isso, o template volta FAILED. Requisitos e alternativa enquanto a categoria não é liberada em Política de templates.

Passo a passo

1

Crie o template de autenticação

Você só escolhe o nome. O conteúdo é fixo: a Arara envia à Meta o texto {{1}} é o seu código de verificação com o botão Copiar código. body continua obrigatório na requisição. Não envie buttons.
Acompanhe a aprovação com GET /v1/templates/{id}/status (o id é o UUID devolvido na criação) ou pelo webhook template.updated. Também dá para criar pelo painel.
2

Guarde as tentativas de login

Cada tentativa de login tem um id, o telefone, o hash do código, a expiração e os contadores. O exemplo usa Map em memória para deixar a interface explícita. As três operações precisam ser atômicas, senão duas requisições simultâneas furam as regras.
store.js
Em produção, troque por banco ou cache compartilhado entre as instâncias:
3

Gere, envie e valide o código

O código nunca é guardado em texto puro: fica só o HMAC-SHA256 dele com OTP_SECRET. A Idempotency-Key vem do id da tentativa e do número do envio, então um retry da mesma chamada não entrega o código duas vezes.
otp.js
O que cada parte garante:
  • Uso único. O código vale 5 minutos. Quem acerta só é autorizado se consume devolver a tentativa. Duas verificações simultâneas com o código certo: uma entra, a outra recebe expired.
  • Um código por telefone. createIfAbsent reserva o telefone antes do envio. Pedir login de novo, mesmo ao mesmo tempo, devolve a tentativa ativa em vez de enviar outro código.
  • Limite de tentativas. A contagem acontece dentro de update, antes da comparação. Depois de cinco erros a tentativa é apagada e o usuário começa o login de novo.
  • Comparação em tempo constante. timingSafeEqual compara dois hashes de mesmo tamanho, sem vazar pelo tempo de resposta quantos dígitos bateram.
  • Reenvio limitado. Um reenvio por minuto, três envios por tentativa, reservados em update antes de chamar a API. O código anterior continua valendo até a API aceitar o novo. Se o envio for recusado (saldo, template pausado), o usuário ainda entra com o código que já recebeu. O reenvio recusado conta no limite.
  • Retry sem duplicar. Só erro de rede, 429 e 5xx são retentados, com a mesma Idempotency-Key, respeitando Retry-After. Espera acima de 5 segundos vira erro: o usuário está aguardando na tela de login.
4

Exponha as rotas de login

server.js
Rode e teste:
Quando verifyLogin devolve ok: true, crie a sessão do usuário dono daquele telefone.

Em produção

  • Limite também por IP. O exemplo limita por telefone e por tentativa. Aplique um limite por IP nas três rotas, senão alguém dispara códigos para vários números às suas custas.
  • Nunca registre o código. Nem em log, nem em URL. O exemplo loga só o id da tentativa e o código de erro da API.
  • Trate a falha de entrega. A API responde 202 e a entrega chega depois, pelo webhook message.status_updated. Com failed, ofereça outro canal (SMS ou e-mail). Ver Erros de envio.

Próximos passos

Webhooks

Receba o status de entrega do código.

Política de templates

Quem pode criar template de autenticação.

Mensagens

Campos e erros do envio.