1) Descubra o “contrato” do provedor (o que é assinado)
Antes de abrir o n8n, confirme quais campos entram no HMAC: corpo bruto (raw body) ou JSON normalizado, caminho/URL, query string, timestamp e qual header carrega a assinatura. Provedores variam muito: alguns assinam "timestamp + '.' + body", outros assinam só o body. Se você não tiver a documentação, peça um exemplo real de request e headers e trate como contrato.
2) Capture o request no Webhook node (sem “transformar” cedo demais)
Crie um Webhook node e garanta que você consiga acessar: headers, query e o body. O ponto crítico: muitos HMACs usam o corpo exatamente como chegou (bytes). Se você parseia e re-stringifica, a assinatura pode não bater por causa de espaços, ordem de campos ou encoding. Quando o provedor assina o raw body, tente preservar o conteúdo original (ou use a opção/mecanismo disponível no seu setup para obter o corpo bruto).
3) Armazene o secret corretamente (não cole no workflow)
Guarde o secret fora do fluxo, usando o mecanismo de secrets/variáveis de ambiente do seu ambiente. No workflow, referencie o secret por variável/credencial. Isso reduz vazamento em exportação, logs e prints.
4) Recalcule a assinatura no n8n (Crypto) com o mesmo algoritmo
Use um Code node (JavaScript) para calcular o HMAC com o algoritmo exigido (ex.: sha256). Construa exatamente a “string para assinar” do jeito que o provedor define. Atenção a detalhes chatos: encoding (utf8), base64 vs hex, prefixos no header (ex.: "sha256=") e presença de quebras de linha.
5) Compare assinatura recebida vs calculada (sem abrir brecha)
Compare os valores após normalizar formato (remover prefixos, padronizar maiúsculas/minúsculas quando aplicável). Evite comparação ingênua se você estiver num cenário sensível: idealmente use comparação de tempo constante (quando disponível). Na prática do n8n, o mínimo é: comparar strings já normalizadas e falhar fechado (se qualquer coisa estiver ausente, negar).
6) Valide timestamp/nonce para bloquear replay attack
Se o provedor envia timestamp, rejeite requests fora de uma janela curta (por exemplo, alguns minutos). Se houver nonce/ID do evento, registre-o (em Redis/DB) e recuse repetidos por um período. Isso evita replays mesmo com assinatura válida.
7) Responda rápido e com status correto
Se a assinatura falhar, responda 401/403 imediatamente. Se passar, prossiga e retorne 200/202 conforme o esperado. Se o processamento for pesado, prefira enfileirar/assíncrono para não estourar timeout do provedor.
O que é assinatura HMAC em webhook (e por que dá trabalho no n8n)
Assinatura HMAC é um jeito de provar que o request veio de quem diz que veio: o provedor calcula um código (hash autenticado) usando um secret compartilhado e manda esse valor num header. Você recalcula no seu lado e compara.
Na prática, o “trabalho” aparece nos detalhes: qual parte do request entra na assinatura (raw body? JSON?), qual encoding, qual algoritmo e como lidar com replay (alguém reenvia o mesmo request). É aqui que automações quebram — ou, pior, passam falsos positivos.
Exemplo de lógica (genérica) para HMAC SHA-256 no Code node
Abaixo vai um exemplo conceitual. Você precisa adaptar para o seu provedor (string para assinar, header e formato). Use como esqueleto mental, não como “copiar e colar sem ler”.
- Leia assinatura do header: ex. x-signature (ou equivalente).
- Leia timestamp: ex. x-timestamp (se existir).
- Monte a mensagem: ex. `${timestamp}.${rawBody}` (exemplo comum, mas não universal).
- Calcule HMAC SHA-256 com o secret.
- Normalize formatos (hex/base64, prefixos) e compare.
- Se falhar, finalize o fluxo retornando 401/403.
Checklist rápido de debug quando “não bate a assinatura”
Quando a assinatura não confere, quase sempre é por causa de string diferente do lado do provedor. Antes de culpar o n8n, passe por este checklist.
| Sintoma | Causa provável | Como testar/arrumar |
|---|---|---|
| Assinatura nunca confere, mesmo com secret certo | Você está assinando JSON reformatado, mas o provedor assinou raw body | Compare o body bruto capturado com o que você usou para calcular; evite parse/restringify antes do HMAC |
| Confere às vezes, falha em payloads específicos | Diferença de encoding/escape ou campos com caracteres especiais | Force UTF-8 e valide se quebras de linha e barras estão idênticas ao original |
| Assinatura confere, mas eventos duplicam | Falta validação de timestamp/nonce (replay) | Implemente janela de tempo e dedupe por event-id/nonce em armazenamento |
| Confere localmente, falha em produção | Secrets divergentes entre ambientes ou header removido por proxy | Valide variável de ambiente no runtime e confira se reverse proxy encaminha headers |
Boas práticas que evitam dor de cabeça (e incidente)
Falhar fechado: se faltar assinatura, timestamp ou secret, trate como inválido.
Não logue o secret nem a assinatura completa em texto puro; se precisar, masque (ex.: últimos 6 caracteres).
Proteja o endpoint: se fizer sentido, restrinja por IP/ASN do provedor (sem confiar só nisso).
Separe validação de autenticação do resto do fluxo: valide primeiro, processe depois.
Se o webhook dispara processos longos, enfileire ou desacople para reduzir timeout e retries agressivos do provedor.
Perguntas frequentes
Preciso de HMAC se meu webhook já está em HTTPS?
Qual é a diferença entre comparar assinatura em hex e em base64?
Como evitar replay attack no webhook validado por HMAC?
O que fazer quando o provedor assina o body “cru”, mas o n8n não me entrega o raw body igual?
Leia também
Webhook no n8n: como receber, tratar e responder HTTP (sem gambiarra)
Aprenda a criar um webhook no n8n, validar assinatura, tratar payload, evitar duplicidade e responder HTTP 200/400/500 com padrão de produção.
Ler →
Como gerenciar secrets e credenciais no n8n self-hosted (sem vazar dados e sem dor)
Aprenda como organizar, proteger e rotacionar secrets e credenciais no n8n self-hosted: variáveis de ambiente, criptografia, permissões, logs, backups e checklist de produção.
Ler →
Como expor webhooks do n8n com HTTPS (reverse proxy, porta 443 e tunnel) sem virar refém de gambiarra
Guia prático para publicar webhooks do n8n com HTTPS usando Nginx/Caddy/Traefik ou tunnel. Inclui checklist de segurança, variáveis do n8n e erros comuns (URL errada, 404, loop de redirect).
Ler →
Rate limit, retry e backoff: como parar de quebrar automação em API (n8n, Make, Zapier)
Guia direto para lidar com rate limit (429), retries e backoff em automações com APIs. Aprenda padrões práticos para n8n, Make e Zapier e evite falhas intermitentes, duplicidades e banimentos.
Ler →