DEV Community

Kairox
Kairox

Posted on

SMS, chamada de voz ou app: como escolher o método de 2FA certo pro seu produto

Toda vez que alguém pergunta "qual método de autenticação em duas etapas eu devo usar", a resposta padrão que circula por aí é "TOTP é mais seguro, use sempre". Tecnicamente correto, mas incompleto. Segurança não é a única variável que importa quando você está desenhando um fluxo de autenticação — taxa de conversão, custo operacional e alcance geográfico do seu usuário pesam tanto quanto, e ignorar isso costuma gerar decisão de arquitetura que parece certa no papel e falha na adoção real.

Passei por essa decisão em mais de um projeto, e o que aprendi é que não existe resposta única — existe a resposta certa pro contexto específico do produto. Vou tentar destrinchar os trade-offs reais de cada opção.

SMS: o padrão de fato, com todos os problemas conhecidos

SMS ganhou o mercado não porque é o método mais seguro, mas porque é o de menor fricção. Não exige instalar nada, funciona em qualquer celular com sinal, e o usuário já entende o fluxo sem precisar de explicação — recebeu código, digitou, pronto.

Os problemas são conhecidos: vulnerabilidade a SIM swap, dependência de infraestrutura de operadora que varia de confiabilidade por região, custo por envio que escala com volume, e latência de entrega que pode variar de segundos a minutos dependendo do país. Pra produtos com base de usuário internacional, essa variação de confiabilidade entre países é o problema mais subestimado — o que funciona perfeitamente testando com número local pode falhar silenciosamente com usuário de outro continente.

async function sendSmsOtp(phone, code) {
  try {
    await smsProvider.send({
      to: phone,
      body: `Seu código: ${code}`,
    });
    return { success: true };
  } catch (err) {
    // não assuma que falha é rara — trate como caminho esperado
    logDeliveryFailure(phone, err);
    return { success: false, fallbackAvailable: true };
  }
}
Enter fullscreen mode Exit fullscreen mode

Quando faz sentido: produto com base de usuário ampla e heterogênea, onde exigir app extra reduziria conversão de cadastro de forma significativa. Praticamente qualquer produto B2C de massa se encaixa aqui, ao menos como opção padrão inicial.

Chamada de voz: o fallback subestimado

Chamada de voz automatizada, lendo o código em voz alta, é frequentemente tratada como recurso secundário — e é mesmo, na maioria dos casos. Mas ela resolve um problema específico que SMS não resolve bem: cenários onde a entrega de texto está falhando (filtro de spam de operadora, número recém-portado com problema de roteamento, país com bloqueio de sender ID) mas a linha ainda recebe chamada normalmente.

Implementar como fallback, não como método primário, costuma ser a decisão certa — o custo por chamada é geralmente mais alto que SMS, e a experiência (atender, ouvir, digitar) tem mais fricção que ler uma mensagem.

async function sendOtpWithFallback(phone, code) {
  const smsResult = await sendSmsOtp(phone, code);
  if (!smsResult.success) {
    await voiceProvider.call({
      to: phone,
      say: `Seu código de verificação é ${code.split('').join(', ')}`,
    });
  }
}
Enter fullscreen mode Exit fullscreen mode

Quando faz sentido: como camada de resiliência atrás de SMS, não como substituto. Produtos com usuário em regiões de entrega de SMS historicamente instável se beneficiam de ativar isso desde o lançamento, não só depois que o problema aparecer.

App autenticador (TOTP): mais seguro, mais fricção de adoção

Google Authenticator, Authy e afins geram código localmente, sem depender de rede de telefonia, o que elimina de uma vez os riscos de interceptação e SIM swap. Do ponto de vista puramente técnico, é superior. O problema é adoção: exigir que o usuário instale um app separado, escaneie QR code e entenda o conceito de código temporário é fricção real, que produtos B2C de massa sentem na taxa de conversão de cadastro.

import { authenticator } from 'otplib';

function generateTotpSecret() {
  return authenticator.generateSecret();
}

function verifyTotp(token, secret) {
  return authenticator.verify({ token, secret });
}
Enter fullscreen mode Exit fullscreen mode

Quando faz sentido: produtos onde o usuário já tem maior tolerância a fricção de segurança em troca de confiança — fintech, ferramenta corporativa, produto B2B técnico. Também faz sentido oferecer como opção avançada opcional em qualquer produto, pro usuário que já entende o valor e quer ativar por conta própria.

O erro comum: escolher um método só, pra sempre

O padrão que vejo mais gerar problema não é escolher o método errado — é tratar a escolha como definitiva e única, sem plano de evolução. Produto lança só com SMS, cresce, ganha usuário internacional, e só aí descobre que precisa de voz como fallback e TOTP como opção avançada. Nada impede desenhar a arquitetura de autenticação já pensando em múltiplos métodos desde o início, mesmo que só um esteja ativo no lançamento.

const authMethods = {
  sms: { primary: true, fallback: false },
  voice: { primary: false, fallback: true },
  totp: { primary: false, fallback: false, optIn: true },
};

async function sendVerification(user, method = 'sms') {
  const config = authMethods[method];
  if (!config) throw new Error('Método não suportado');
  return method === 'sms' ? sendOtpWithFallback(user.phone, code) : null;
}
Enter fullscreen mode Exit fullscreen mode

Estruturar assim desde cedo — mesmo com só um método ativo — evita reescrever o fluxo inteiro quando a necessidade de adicionar outro método aparecer, e ela costuma aparecer mais cedo do que se imagina.

Testando os três antes de decidir

Uma coisa que ajuda bastante antes de bater o martelo é simular os três métodos com usuário de teste real, não só com o seu próprio número do seu próprio país. Pra isso, sem precisar arranjar chip físico de várias regiões, dá pra usar número virtual — a numerovirtual.net tem cobertura de vários países que serve bem pra esse tipo de teste, testando entrega de SMS e de chamada de voz de fato, em vez de assumir que vai funcionar igual em todo lugar só porque funcionou no seu teste local.

Não existe "o melhor", existe o adequado ao contexto

Se seu produto é B2C de massa, comece com SMS e adicione voz como fallback assim que tiver volume suficiente pra justificar o custo. Se é B2B técnico ou lida com dado sensível, considere TOTP como padrão desde o início, com SMS como opção de recuperação. Se atende usuário internacional, teste entrega em múltiplos países antes de assumir que o comportamento vai ser uniforme.

A pergunta certa nunca é "qual é o método mais seguro" isolado de contexto — é "qual combinação de segurança, custo e fricção faz sentido pro usuário que meu produto realmente tem".

Top comments (0)