Aula "nm66 - Protegendo o Webhook" sobre segurança de webhooks no…
INEMA
breve, jti e scopes minimizados.
Como fazer – exp 5–15 min; incluir jti; validar issuer/audience; checar blacklist.
Exemplo de claims
sub: user_123
scope: posts:read,posts:write
aud: n8n-webhooks
iss: seu-backend
exp: 1734398400
jti: 7b7c1f...
Resposta esperada – 401 para exp expirado, aud/iss incorretos ou jti revogado.
- mTLS atrás de proxy O que é – Exigir certificado cliente em Nginx/API Gateway e só então repassar.
Como fazer – Validar client cert CA no Nginx e adicionar um header interno X-Client-Cert: valid. – No n8n, recusar se header ausente.
Resposta esperada – Só quem tem cert cliente chega no n8n; demais 400/403 no edge.
- Segredos fora do fluxo O que é – Nunca hardcode. Use Credentials/variáveis de ambiente.
Como fazer – Referenciar \$env.MEU_SECRETO ou credenciais do n8n. – Negar logs sensíveis em nós de debug.
Resposta esperada – Nenhum segredo aparece em histórico ou versionamento.
- Honeytoken e canário O que é – Chave falsa monitorada para detectar vazamento.
Como fazer – Criar X-Api-Key-canary aceita só no edge e alerta. – Se usada, alertar e rotacionar chaves reais.
Resposta esperada – Alerta imediato e trilha para resposta a incidentes.
- Limitar métodos e content-type O que é – Recusar GET/PUT/DELETE e tipos fora de application/json.
Como fazer – No Webhook: método POST. – Function: checar \$json.headers['content-type'] === 'application/json'.
Resposta esperada – 405 ou 415 para métodos/tipos inválidos.
- Concurrency guard e backpressure O que é – Evitar estouro de nós caros (LLM, banco).
Como fazer – Gate por fila (ex.: Redis) ou contador em \$global. – Se acima do limite, responder 429 com Retry-After.
Resposta esperada – 429 sob pico; sistema estável.
- Rotação automática de chaves O que é – Trocar segredos periodicamente sem downtime.
Como fazer – Manter K1 e K2 válidos; aceitar ambos por janela; assinar novo com K2.
Resposta esperada – Nenhuma quebra durante rotação; tokens antigos expiram naturalmente.
- Sanitização e redaction nos logs O que é – Remover Authorization, cookies, PII de logs e respostas de erro.
Como fazer – Function que zera cabeçalhos sensíveis antes de salvar/emitir logs. – Mensagens de erro genéricas: nunca diga se faltou senha ou token específico.
Resposta esperada – Logs úteis sem segredos; menos engenharia reversa por atacante.
- Pré-validação no edge com Turnstile/Proof-of-Work opcional O que é – Para endpoints públicos, exigir um desafio leve.
Como fazer – Cloudflare Turnstile no cliente; backend verifica token antes de repassar.
Resposta esperada – Bots simples ficam de fora; menos spam.
Exemplos de respostas padrão no n8n – 200 ok – 400 invalid schema – 401 unauthorized/invalid signature/token expired – 403 forbidden – 413 payload too large – 415 unsupported media type – 429 too many requests
Checklist de operação – WAF/edge com allowlist e rate limit ativo. – Método de autenticação aplicado + HMAC ou JWT curto. – Anti-replay ligado (timestamp/nonce). – Schema e tamanho validados. – Logs com redaction e alertas 401/403/429. – Plano de rotação de chaves e tokens. – Testes automatizados de segurança (curl/Postman/CI) cobrindo 200 e falhas.
Aqui vão hacks práticos para blindar webhooks no n8n, além do básico (Basic Auth, Header API Key e JWT). Curto e direto, com exemplos e respostas esperadas.
Resumo rápido – Minimize superfície de ataque no edge (WAF, rate limit, allowlist). – Verifique autenticidade e integridade de cada requisição (HMAC/JWT). – Evite replay, vazamento e abuso (nonce, expiração, idempotência). – Valide conteúdo e tamanho antes de tocar em recursos caros (schema, limites). – Observe, alerte e rotacione segredos como rotina.
- Rate limiting e IP allowlist no edge O que é – Bloquear/limitar chamadas antes do n8n, via Cloudflare, Nginx ou API Gateway.
Como fazer – Cloudflare: regra WAF para permitir apenas países/IPs/clientes. – Nginx: limitar por IP/rota com limit_req e allow/deny.
Exemplo Nginx
limit_req_zone $binary_remote_addr zone=wl:10m rate=5r/s;
server {
location /webhook/ {
allow 200.201.0.0/16; deny all;
limit_req zone=wl burst=10 nodelay;
proxy_pass http://n8n:5678;
}
}
Resposta esperada – Tráfego não autorizado recebe 403; floods recebem 429 antes de atingir o n8n.
- Assinatura HMAC do corpo (integridade) O que é – Emissor calcula HMAC-SHA256 do body com um segredo; você valida no n8n.
Como fazer no n8n – Header X-Signature: hex/base64 do HMAC(body, secret). – Function antes de qualquer nó caro: recalcular e comparar.
Exemplo Function (Node.js)
c```onst secret = $env.SECRET_WEBHOOK; // use Credentials/Env const sig = $json.headers['x-signature'] || $json.headers['X-Signature']; const body = JSON.stringify($json.body || {}); const crypto = require('crypto'); const calc = crypto.createHmac('sha256', secret).update(body).digest('hex'); if (!sig || sig !== calc) { return [{ status: 401, error: 'invalid signature' }]; // pare o fluxo } return [{ ok: true }];
curl de teste
B```ODY='{"msg":"ping"}'
SIG=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "SEU_SEGREDO" -hex | cut -d' ' -f2)
curl -X POST "https://seu.webhook" -H "X-Signature: $SIG" -H "Content-Type: application/json" -d "$BODY"
Resposta esperada – 200 quando assinatura bate; 401 quando diverge.
- Anti-replay com nonce e timestamp O que é – Evitar reenvio do mesmo pacote.
Como fazer – Headers X-Timestamp (epoch seg) e X-Nonce (uuid). – Recusar se clock drift > 120s ou nonce já visto (cache KV/DB com TTL).
Exemplo Function
co```nst ts = Number($json.headers['x-timestamp'] || 0); const nonce = $json.headers['x-nonce']; if (!ts || !nonce) return [{ status: 400, error: 'missing ts/nonce' }]; if (Math.abs(Date.now()/1000 - ts) > 120) return [{ status: 401, error: 'stale' }];
// checar nonce (ex.: Redis/SQLite). Pseudo: const seen = $flow.get(nonce); if (seen) return [{ status: 401, error: 'replay' }]; $flow.set(nonce, true, 180); // TTL 3 min return [{ ok: true }];
```Resposta esperada – 401 para timestamps velhos ou nonce repetido.
- JSON Schema e limites de payload O que é – Validar formato e tamanho antes de acionar LLM/DB.
Como fazer – Function com Ajv ou validação simples; rejeitar > X KB.
Exemplo simples
co```nst raw = $json.body; const size = Buffer.byteLength(JSON.stringify(raw)); if (size > 50*1024) return [{ status: 413, error: 'payload too large' }]; if (!raw || typeof raw !== 'object' || typeof raw.mensagem !== 'string') { return [{ status: 400, error: 'invalid schema' }]; } return [{ ok: true }];
```Resposta esperada – 413 para excesso; 400 para schema inválido.
- Idempotência por chave O que é – Garantir que requisições repetidas não executem duas vezes.
Como fazer – Header Idempotency-Key; armazene resultado por janela de tempo.
Exemplo
co```nst key = $json.headers['idempotency-key']; if (!key) return [{ status: 400, error: 'missing idempotency key' }]; if ($flow.get('idem:' + key)) return [{ status: 200, reused: true }]; $flow.set('idem:' + key, true, 600); // 10 min return [{ ok: true }];
```Resposta esperada – Primeira vez executa; repetição retorna reused sem refazer.
- JWT de curta duração + jti e escopos O que é – Tokens Bearer com exp
planeje rotação periódica de senhas/chaves/segredos. 7. Logs: registre tentativas 401/403 e alerte. 8. Produção vs teste: use segredos distintos. 9. Conteúdo: valide schema do body (ex.: JSON Schema via Function) antes de prosseguir. 10. Respostas: retorne 401/403 e nunca detalhe o motivo específico em produção.
Testes rápidos com curl
- Sem proteção (esperado 200 quando desprotegido) curl -X POST "https\://SEU_WEBHOOK" -H "Content-Type: application/json" -d "{"mensagem":"ping"}"
- Basic Auth ok curl -X POST "https\://SEU_WEBHOOK" -u "svc-interno\:SUA_SENHA" -H "Content-Type: application/json" -d "{"mensagem":"ping"}"
- Header Auth ok curl -X POST "https\://SEU_WEBHOOK" -H "X-Api-Key: SUA_CHAVE" -H "Content-Type: application/json" -d "{"mensagem":"ping"}"
- JWT ok curl -X POST "https\://SEU_WEBHOOK" -H "Authorization: Bearer SEU_TOKEN_JWT" -H "Content-Type: application/json" -d "{"mensagem":"ping"}"
- JWT expirado (esperado 401) – Gere um token com exp no passado e repita o passo 4.
Checklist final – Webhook com um dos métodos ativos (Basic, Header ou JWT). – Segredo/credenciais guardados em Credentials. – Testes 200/401 via curl/Postman. – Logs/alertas ligados. – Plano de rotação de segredos e chaves. – Se houver usuários/planos/roles, use JWT + Switch.
Resumo completo com tópicos, exemplos e respostas
O que configurar primeiro? – Ativar autenticação no Webhook e testar em ambiente de teste. Exemplo: Header Auth com X-Api-Key e chave de 64+ chars.
Qual método escolher? – Interno/rápido: Basic Auth. – Serviço/integração B2B: Header Auth (X-Api-Key). – Usuários, planos, permissões e expiração: JWT.
Como gerar um JWT seguro? – Assine com HS256 e segredo de 256 bits. – Inclua sub, role, plan, iat, exp. Resposta prática: gere o secret no servidor e assine o token no backend; evite ferramentas online com segredos reais.
Como rotear por role/plan? – Decode do JWT no fluxo (Function) e use Switch para separar admin vs user, vip vs basic.
Como evitar vazamentos? – Não exponha URLs de Production; use nomes não óbvios; limite IP; rotacione chaves.
Passo a passo para proteger webhooks no n8n
Preparação
- Crie um fluxo simples com um nó Webhook (POST) e um nó de resposta (por exemplo, Respond to Webhook ou Set → Respond to Webhook), só para testar.
- Copie as URLs de Test e Production do Webhook.
Método 1: Basic Auth (usuário e senha)
- No nó Webhook, abra Authentication e escolha Basic Auth.
- Clique em Create New Credential e defina:
- Username: ex. svc-interno
- Password: gere uma senha forte (32+ chars). 3. Salve o fluxo e ative. 4. Teste com curl: curl -X POST "https\://SEU_WEBHOOK" -u "svc-interno\:SUA_SENHA" -H "Content-Type: application/json" -d "{"mensagem":"ping"}" 5. Se quiser validar dentro do fluxo (opcional): adicione um IF para checar campos do body/headers e retornar status 401 se faltar credencial.
Quando usar – Rápido para testes internos. Limitações – Se a senha vazar, qualquer um acessa. Rotacione senhas com frequência.
Método 2: Header Authorization (API Key em cabeçalho)
- No nó Webhook, selecione Header Auth.
- Configure:
- Header Name: Authorization (ou X-Api-Key)
- Header Value: uma chave forte, por exemplo: api_live_9b0f… (64+ chars). 3. Salve e ative. 4. Teste com curl: curl -X POST "https\://SEU_WEBHOOK" -H "Authorization: api_live_9b0f..." -H "Content-Type: application/json" -d "{"mensagem":"ping"}" 5. Para múltiplos clientes/serviços, gere uma chave por cliente e armazene a lista/validação no próprio n8n (ex.: em uma tabela, Google Sheet, DB) antes de prosseguir no fluxo.
Quando usar – Integrações B2B ou entre serviços. Vantagem – Você identifica quem chamou pelo valor da chave. Cuidados – Rotacione chaves; não versionar chaves no repositório.
Método 3: JWT (Json Web Token com expiração e claims)
- No nó Webhook, escolha JWT Authorization.
- Em Credentials, crie uma credencial JWT:
- Algorithm: HS256
- Secret: gere um segredo aleatório de 256 bits (ex.: no Node: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))") 3. Gere o token JWT para o chamador (no seu backend). Para testes, use uma ferramenta local/segura. Payload sugerido: { "sub": "user_123", "email": "user@exemplo.com", "role": "admin", "plan": "vip", "iat": 1734312000, "exp": 1734398400 } Observações – iat/exp são timestamps em segundos. – O Secret usado para assinar deve ser o mesmo configurado no Webhook. 4. Envie chamadas com o cabeçalho: Authorization: Bearer SEU_TOKEN_JWT Exemplo curl: curl -X POST "https\://SEU_WEBHOOK" -H "Authorization: Bearer SEU_TOKEN_JWT" -H "Content-Type: application/json" -d "{"mensagem":"ping"}" 5. Roteie por claims – Após o Webhook, adicione um Function (ou Code) para extrair claims, caso o n8n não exponha automaticamente o payload decodificado: // Lê o JWT do header e decodifica o payload (já foi verificado pelo Webhook) const auth = \$json.headers.authorization || ''; const token = auth.split(' ')[1] || ''; const payloadPart = token.split('.')[1] || ''; const payload = JSON.parse(Buffer.from(payloadPart, 'base64url').toString('utf8')); return [{ jwt: payload }]; – Use um Switch para ramificar por {{\$json.jwt.role}} (admin, user, etc.) ou {{\$json.jwt.plan}} (vip, basic). 6. Expiração e revogação – Defina exp curto (ex.: 15 min) e renove conforme necessário. – Para revogar, mantenha uma lista de jti (ID do token) ou sub bloqueados e cheque antes de seguir.
Quando usar – Apps, usuários e integrações que exigem autorização granular, expiração e contexto do usuário. Vantagens – Permite decisões no fluxo por role/plan/permissões.
Dicas de segurança adicionais
- Nome do Webhook: evite nomes previsíveis na URL.
- IP allowlist (se possível): filtre origem com um Reverse Proxy (ex.: Nginx/Cloudflare) ou Firewall.
- Anti-replay: inclua no payload nonce e timestamp; rejeite requisições fora de janela curta.
- Rate limit: limite por IP/chave no proxy antes do n8n.
- Segredos: mantenha apenas em Credentials do n8n; nunca em campos de texto/expressões.
- Rotação:
Resumo sobre proteção de webhooks no N8N:
A importância de proteger webhooks para evitar acessos não autorizados, consumo indevido de tokens de IA e acesso a dados sensíveis. O instrutor demonstra três métodos de autenticação e mostra, na prática, como cada um funciona.
1. Riscos de não proteger um webhook
- Qualquer pessoa com a URL pode acionar o fluxo.
- Possibilidade de consumir recursos (tokens, API) sem permissão.
- Acesso a bancos de dados e informações de clientes.
- Quebra ou mau uso de automações.
2. Boas práticas iniciais
- Evitar nomes óbvios na URL do webhook.
- Sempre aplicar pelo menos uma camada de autenticação.
3. Três métodos de autenticação
- Basic Auth (usuário e senha)
- Configura credenciais simples.
- Fácil de implementar, mas menos seguro se compartilhado.
- Header Authorization (API Key)
- Chave personalizada enviada no cabeçalho.
- Útil para identificar serviços emissores (B2B).
- Permite gerar chaves diferentes para cada cliente ou serviço.
- JWT (Json Web Token)
- Autenticação avançada com informações no payload.
- Possibilita incluir dados como nome, e-mail, papel, permissões, plano contratado, validade, etc.
- Permite filtragem e rotas personalizadas dentro do fluxo.
- Mais seguro e versátil para integrações complexas.
4. Conclusão
- Sempre proteger webhooks, mesmo de teste.
- Escolher o método de autenticação conforme a necessidade de segurança e personalização.
- Basic Auth e Header Auth servem para a maioria dos casos, mas JWT é ideal quando se precisa transmitir e validar dados do usuário.
Seus Webhooks estão em perigo! 🛑
Se você trabalha com clientes e usa webhooks no N8N, precisa ver e sem falta.
💥 Até pouco tempo atrás, eu mesmo não dava tanta importância…
O alerta foi dado quando disse: “Tem gente que perdeu dados porque não tinha os webhooks protegidos.”
E ele estava totalmente certo. Porque se eles não estiverem protegidos: ❌ Qualquer pessoa pode acessar seu fluxo ❌ Podem consumir seus tokens de IA ❌ Ter acesso a dados dos seus clientes ❌ Ou simplesmente quebrar sua automação
🔥 Por isso, explico as 3 formas de proteger seus webhooks como um PRO: ✅ Basic Auth (usuário e senha) ✅ Header Authorization (tipo API Key) ✅ JWT (autenticação avançada com dados do usuário e tempo de expiração)
Se você trabalha com clientes: isso não é opcional. Coloque pelo menos uma camada de segurança.
Isso pode ser aplicado se você é agência, SaaS, consultor… ou simplesmente cuida das suas automações como deve ser.
nm66 - Protegendo o Webhook
1