Webhooks Explicados: Payloads Assinados e Retentativas
Você acabou de integrar um serviço de terceiros que envia webhooks para o seu endpoint. Tudo funciona nos testes, mas em produção você percebe eventos perdidos, entregas duplicadas e ocasionais preocupações com segurança. Webhooks são simples em conceito, mas complicados na prática—especialmente quando se trata de verificar autenticidade e lidar com falhas.
Este guia explica como proteger webhooks com payloads assinados e implementar mecanismos de retentativa robustos, para que você possa construir integrações confiáveis.
O que são Webhooks?
Webhooks são callbacks HTTP definidos pelo usuário. Quando um evento ocorre em um sistema de origem (por exemplo, um pagamento é concluído), ele envia uma requisição HTTP POST para uma URL que você especifica, contendo dados sobre o evento. Isso permite comunicação em tempo real entre serviços sem polling.
Mas webhooks introduzem desafios: como você sabe que a requisição veio genuinamente do remetente esperado? E se seu endpoint estiver temporariamente fora do ar? É aí que entram os payloads assinados e as retentativas.
Protegendo Webhooks com Payloads Assinados
Um payload assinado usa uma assinatura criptográfica para provar que a requisição se originou do remetente e não foi adulterada. A abordagem comum é HMAC (Hash-based Message Authentication Code) com um segredo compartilhado.
Como Funcionam as Assinaturas HMAC
O remetente calcula um HMAC sobre o corpo da requisição (e às vezes cabeçalhos como timestamp) usando uma chave secreta. A assinatura é enviada em um cabeçalho (por exemplo, X-Signature). Seu servidor recalcula o HMAC e compara com a assinatura recebida. Se corresponderem, a requisição é autêntica.
Aqui está um exemplo mínimo em Python usando Flask:
import hmac
import hashlib
from flask import Flask, request, abort
app = Flask(__name__)
SECRET = b'your_shared_secret'
@app.route('/webhook', methods=['POST'])
def webhook():
signature = request.headers.get('X-Signature')
if not signature:
abort(400, 'Missing signature')
body = request.get_data()
expected = hmac.new(SECRET, body, hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, signature):
abort(401, 'Invalid signature')
# Process the event
return '', 200
Pontos-chave:
- Sempre use uma função de comparação em tempo constante (como
hmac.compare_digest) para prevenir ataques de temporização. - Inclua um timestamp nos dados assinados para prevenir ataques de replay; rejeite requisições mais antigas que alguns minutos.
- Mantenha o segredo seguro—nunca o exponha no lado do cliente.
Medidas Adicionais de Segurança
- HTTPS: Sempre use HTTPS para proteger o payload em trânsito.
- Allowlist de IP: Se o provedor publica faixas de IP, restrinja requisições a esses IPs.
- Idempotência: Use IDs de evento para deduplicar, pois retentativas podem causar duplicatas.
Implementando Retentativas Confiáveis
Consumidores de webhook podem falhar: seu servidor pode estar fora do ar ou o processamento pode expirar. Remetentes devem retentar entregas falhas com backoff exponencial. Como consumidor, você deve lidar com retentativas graciosamente.
No Lado do Remetente (Se Você Está Construindo um Sistema de Webhook)
- Retorne 2xx rapidamente: Confirme o recebimento antes de processar para evitar timeouts. Use uma fila para trabalho assíncrono.
- Retente em caso de falha: Se nenhum 2xx for recebido dentro de um timeout (por exemplo, 5 segundos), retente com atrasos crescentes (por exemplo, 1s, 5s, 30s, 5m, 30m).
- Limite as retentativas: Após um número máximo de tentativas (por exemplo, 5), marque a entrega como falha e alerte.
- Inclua um ID de evento único: Para que os consumidores possam deduplicar.
No Lado do Consumidor (Seu Endpoint)
- Responda rápido: Retorne 2xx imediatamente e processe de forma assíncrona se necessário.
- Seja idempotente: Use o ID do evento para evitar processar o mesmo evento duas vezes.
- Lide com duplicatas: Armazene IDs de eventos processados por um período razoável.
- Registre falhas: Se o processamento falhar, retorne 5xx para acionar uma retentativa, mas garanta que você não fique preso em um loop.
Comparação: Payloads Assinados vs. Autenticação Básica
| Abordagem | Segurança | Complexidade | Proteção contra Replay |
|---|---|---|---|
| Assinatura HMAC | Alta (integridade + autenticidade) | Moderada | Sim (com timestamp) |
| Autenticação Básica | Baixa (credenciais no cabeçalho) | Baixa | Não |
| Allowlist de IP | Média (nível de rede) | Baixa | Não |
Testando Webhooks Localmente
Durante o desenvolvimento, você precisa de uma URL pública para receber webhooks. Ferramentas como ngrok ou localtunnel podem expor seu servidor local. Sempre teste a verificação de assinatura e o comportamento de retentativa com falhas simuladas.
Ao inspecionar payloads de webhook, você pode precisar formatar JSON para legibilidade. O JSON Formatter pode ajudar você a formatar e validar o corpo JSON.
FAQ
O que é um payload de webhook assinado?
Um payload assinado inclui uma assinatura criptográfica (frequentemente HMAC) que permite ao receptor verificar a autenticidade e integridade da requisição.
Quantas vezes um webhook deve ser retentado?
Não há um número fixo; práticas comuns variam de 3 a 10 retentativas com backoff exponencial. O importante é equilibrar confiabilidade com uso de recursos e alertar sobre falhas persistentes.
Posso usar webhooks sem assinaturas?
Não é recomendado. Sem assinaturas, você não pode verificar o remetente, tornando seu endpoint vulnerável a falsificação. Sempre use assinaturas em produção.
Pronto para depurar seus payloads de webhook? Experimente nosso JSON Formatter para validar e formatar dados JSON rapidamente.