Webhooks em KYC, integração segura para decisões que valem dinheiro

UNIFOKAL5 min de leituraProduto e integração

A decisão de uma verificação chega por webhook, e webhook mal integrado vira fraude ou perda de evento. Assinatura HMAC (RFC 2104), idempotência, retentativas e os erros clássicos.

Numa integração de verificação de identidade, o webhook é o momento em que o dinheiro muda de mãos: é por ele que a plataforma avisa que a verificação foi aprovada ou recusada, e é em cima dele que o seu sistema libera a conta, concede o limite ou credita o saldo. Isso faz do webhook a superfície mais sensível da integração inteira. Um endpoint que aceita qualquer POST bem formatado aceita, por definição, um POST forjado por um fraudador que leu a sua documentação.

Este artigo percorre o desenho de uma integração de webhook que aguenta produção: autenticidade, idempotência, retentativas e os erros que aparecem repetidamente em integrações reais.

Autenticidade: assinatura, não origem

A primeira pergunta do seu endpoint diante de uma notificação: quem mandou isso? A resposta errada é confiar na origem da rede, porque IPs de plataformas mudam e cabeçalhos são forjáveis. A resposta consolidada na indústria é a assinatura criptográfica do corpo da mensagem com um segredo compartilhado, usando HMAC, o código de autenticação de mensagem baseado em hash definido na RFC 2104 do IETF, tipicamente com SHA-256.

O contrato funciona assim: a plataforma calcula a assinatura do corpo exato da requisição com o segredo do seu endpoint e a envia num cabeçalho; o seu servidor recalcula com o mesmo segredo e compara. Três detalhes de implementação separam a proteção real da decorativa:

  • O timestamp entra na assinatura. Assinar apenas o corpo permite o replay: reenviar amanhã uma notificação legítima de hoje. Com o horário assinado e uma janela de tolerância curta, a mensagem velha é rejeitada mesmo com assinatura válida. É o desenho documentado publicamente por provedores de pagamento como a Stripe, cuja documentação de webhooks descreve exatamente essa composição de corpo, timestamp e tolerância.
  • A comparação é de tempo constante, para não vazar por temporização quantos bytes da assinatura estavam certos. Bibliotecas padrão têm função própria para isso.
  • O corpo verificado é o corpo cru recebido, byte a byte. Verificar sobre o JSON já interpretado e reserializado quebra a assinatura de formas intermitentes e cria o pior tipo de bug.

O segredo de assinatura é credencial: um por endpoint e por ambiente, guardado como os demais segredos, com rotação possível sem janela de invalidez, o que pede aceitar duas versões do segredo durante a troca.

Idempotência: toda entrega pode acontecer duas vezes

Sistemas de entrega de webhook prometem, com razão, entrega ao menos uma vez. A rede falha, o seu servidor responde lento, o timeout dispara depois de o seu banco já ter gravado, e a plataforma reenvia. Consequência inevitável: o mesmo evento vai chegar mais de uma vez, e o seu processamento precisa ser idempotente, produzir o mesmo estado final na primeira e na quinta entrega.

O mecanismo é registrar o identificador único do evento no mesmo ato transacional que aplica o efeito, e ignorar silenciosamente o identificador repetido. O detalhe que derruba implementações ingênuas é o mesmo ato transacional: checar se o evento existe e depois aplicar o efeito em outra transação abre a janela clássica de corrida em que duas entregas simultâneas passam juntas pela checagem. Em consequência prática para KYC: creditar de novo, liberar de novo, ou notificar o cliente duas vezes.

Idempotência importa dobrado quando o evento dispara movimentação financeira. O princípio de arquitetura que adotamos na UNIFOKAL, e que vale para qualquer integração, é que só o webhook confirmado credita, num único ponto do código: resposta síncrona de API não movimenta dinheiro, e a reconciliação periódica confere se todo evento aplicado corresponde ao estado da plataforma.

Retentativas, ordem e o estado consultável

A política de retentativa da plataforma define o comportamento sob falha: intervalos crescentes, por horas ou dias, até desistir. Do seu lado, três consequências de desenho:

  1. Responda rápido e processe depois. O endpoint valida assinatura, enfileira e responde com sucesso em milissegundos. Processar tudo em linha na requisição transforma qualquer lentidão sua em tempestade de retentativas.
  2. Não assuma ordem. Entre retentativas e eventos concorrentes, o evento mais novo pode chegar antes do mais velho. Decida pelo estado, não pela sequência de chegada: um evento que descreve estado anterior ao que você já tem é ignorável.
  3. Tenha o caminho de reconciliação. Se o seu endpoint ficou fora por mais tempo que a janela de retentativa, eventos se perderam. A integração completa consulta o estado atual pela API da plataforma, na volta de incidentes e periodicamente, e corrige divergências. Webhook é notificação; a fonte da verdade é consultável.

Erros que aparecem em toda auditoria de integração

  • Endpoint sem TLS válido ou com certificado vencido, fazendo a entrega falhar em silêncio.
  • Segredo de assinatura commitado no repositório ou compartilhado entre ambientes de teste e produção.
  • Verificação de assinatura desligada em desenvolvimento e esquecida desligada em produção.
  • Resposta de sucesso antes de persistir, perdendo o evento quando o processo morre no meio.
  • Fila de processamento sem tratamento de veneno: um evento malformado que sempre lança erro trava as retentativas atrás dele.
  • Logs do corpo do webhook com dados pessoais completos, criando um segundo banco de dados sensível não governado, problema que a Lei 13.709/2018 alcança do mesmo jeito que o banco principal.

Nada nesta lista é exótico; tudo já foi visto em integrações reais de produção. A boa notícia é que o custo de fazer certo é baixo e pontual, uma vez na integração, enquanto o custo de fazer errado é recorrente e cresce com o volume. Teste a assinatura com casos inválidos, force entregas duplicadas no sandbox, derrube o seu endpoint de propósito e veja a recuperação acontecer, antes de o primeiro cliente real depender disso.

Fontes citadas

  • RFC 2104, do IETF, HMAC: Keyed-Hashing for Message Authentication
  • Documentação pública de webhooks da Stripe, exemplo de referência da indústria para assinatura com timestamp e janela de tolerância
  • Lei 13.709/2018, LGPD, sobre o alcance do tratamento de dados pessoais em logs e sistemas auxiliares, disponível no portal do Planalto: planalto.gov.br