Integração e API
Assinatura de Webhook
Assinatura de Webhook é um mecanismo que autentica a origem e a integridade do corpo recebido por meio de HMAC ou assinatura assimétrica. Stripe usa `Stripe-Signature` com timestamp e segredo; GitHub usa `X-Hub-Signature-256` com HMAC-SHA-256. O receptor valida os bytes brutos, compara em tempo constante e aplica tolerância contra replay. Deve ser preferida a um token fixo no URL, mas ainda exige HTTPS, rotação de segredo e processamento idempotente.
🔀 Tipos de Comunicação
HMAC-SHA256
HMAC com segredo compartilhado
O provedor e o receptor compartilham um segredo. O provedor calcula HMAC sobre o corpo bruto e, frequentemente, timestamp e versão. O receptor repete o cálculo e compara. GitHub envia `X-Hub-Signature-256` no formato `sha256=<hex>`. Stripe envia uma lista de elementos em `Stripe-Signature`, incluindo `t=` e assinaturas `v1=`. HMAC-SHA-256 fornece autenticação e integridade quando o segredo permanece confidencial. Não cifra o payload. O corpo ainda precisa de HTTPS. O receptor não deve parsear JSON, reserializar e então calcular, porque espaços, ordem e encoding mudam bytes. Frameworks precisam disponibilizar o raw body. A comparação usa função de tempo constante, como `hmac.compare_digest`, para reduzir vazamento por timing.
PUBLIC KEY
Assinatura assimétrica com chave pública
Alguns provedores assinam com Ed25519, RSA ou ECDSA e publicam chaves verificadoras. O receptor não guarda segredo capaz de assinar, apenas chave pública. Isso melhora distribuição para muitos consumidores e reduz impacto de vazamento do verificador. A implementação precisa validar algoritmo, key ID, cadeia ou conjunto JWKS, timestamp e canonicalização. Não aceitar algoritmo indicado livremente pelo atacante sem allowlist. Chaves rotacionam. O cache precisa atualizar. O evento pode transportar assinatura em cabeçalho ou envelope. Assinatura assimétrica custa mais CPU que HMAC, mas em webhooks de baixa frequência é irrelevante. A escolha depende do provedor; o receptor implementa o esquema documentado, não inventa outro.
TIMESTAMP
Timestamp e proteção contra replay
Uma assinatura válida pode ser capturada e reenviada. Incluir timestamp no conteúdo assinado permite rejeitar eventos antigos. Uma tolerância de 300 s é comum em SDKs e exemplos de mercado, mas precisa considerar relógio e latência. O servidor usa NTP. A verificação checa se `abs(now - timestamp)` está dentro da janela. Isso não impede replay dentro dela. O receptor também armazena `event_id` ou delivery ID por um período e processa uma vez. GitHub envia `X-GitHub-Delivery`; Stripe eventos possuem ID. A combinação de timestamp e deduplicação é mais forte. Não se deve desativar a tolerância para resolver relógio errado. Corrigir NTP. A janela maior aumenta replay; menor aumenta falsos negativos.
CANONICAL
Canonicalização e assinatura de campos selecionados
Alguns esquemas não assinam o corpo bruto; constroem uma string canônica com método, caminho, timestamp, headers e hash do corpo. AWS Signature Version 4 é um exemplo de assinatura de requisições, embora não seja especificamente webhook. O contrato precisa definir normalização de URL, query, maiúsculas, espaços e encoding. Pequena divergência invalida. Para webhooks, assinar o raw body é mais simples, mas não protege cabeçalhos não incluídos. Se o receptor usa host ou tipo de evento para autorização, esses campos devem estar no conteúdo assinado ou ser validados por fonte confiável. Proxies podem alterar headers. A cadeia precisa preservar o que faz parte da assinatura.
✅ Vantagens Arquiteturais
⚡
Verifica origem sem depender apenas do endereço IP
IPs de provedores podem mudar, usar CDN ou compartilhar infraestrutura. Allowlist de IP é camada adicional, não identidade criptográfica. A assinatura prova que quem conhece a chave produziu o valor para aquele corpo. O receptor ainda precisa usar endpoint secreto? Não como requisito principal. URLs podem vazar em logs. O segredo fica fora da URL. Em integrações de casa inteligente, um evento `door.unlocked` não deve ser aceito apenas porque chegou de uma faixa de nuvem. A assinatura reduz falsificação. Se o segredo vaza, qualquer pessoa pode assinar; rotação e armazenamento seguro permanecem.
⚡
Detecta alteração do payload em trânsito ou por intermediários
Se um byte muda, o HMAC calculado difere. TLS já protege o canal, mas a assinatura mantém verificação no nível da mensagem, útil quando proxies, filas e gateways intermediários participam. O serviço pode validar na borda e anexar uma identidade interna assinada ou contexto confiável. Não é recomendável validar uma vez e depois distribuir o corpo sem preservar a evidência. Se o raw body é transformado antes da verificação, falha. O pipeline deve capturar bytes, validar e só então parsear. Limites de tamanho e Content-Type são aplicados para evitar abuso. Assinatura válida não torna o conteúdo semanticamente autorizado; eventos e recursos ainda precisam de checagem.
⚡
Permite rotação gradual de segredos
Provedores podem manter segredo antigo e novo durante uma janela. Stripe pode incluir múltiplas assinaturas no cabeçalho durante rotação, conforme o fluxo. O receptor tenta chaves ativas e registra qual funcionou, sem expor. A rotação precisa de inventário de endpoints, cofre e data. Um segredo por endpoint ou ambiente reduz blast radius. Não reutilizar produção em teste. O segredo não deve aparecer em código, imagem Docker, log ou painel. Após validar uso da nova chave, remover antiga. O monitoramento de falhas durante a janela detecta instâncias desatualizadas. A rotação deve ser ensaiada antes de incidente.
⚡
Favorece interoperabilidade segura entre nuvens e sistemas locais
Um API Gateway pode validar webhook e publicar evento interno em MQTT, AMQP ou Event Bus. O sistema local não precisa conhecer o segredo do provedor. Ele confia no gateway por mTLS ou rede segmentada. Isso reduz distribuição de chaves. O detalhe de interoperabilidade precisa ser explícito: a assinatura externa cobre o corpo original; após transformação, um novo contrato interno é necessário. Propagar `event_id`, `provider`, `verified_at` e hash ajuda auditoria. Não se deve copiar o cabeçalho e afirmar que ele valida um JSON transformado. A verificação pertence à mensagem exata.
⚡
Cria critério objetivo para aceitar ou rejeitar entregas
O receptor rejeita assinatura ausente, formato inválido, timestamp fora da janela, algoritmo não permitido e mismatch. Pode responder 400 ou 401 conforme contrato. O provedor costuma retentar respostas não 2xx. Antes de responder, a aplicação deve decidir se enfileira o evento. Uma prática robusta é verificar, persistir/enfileirar e responder rapidamente 2xx; processamento pesado ocorre depois. Se o evento é inválido, não enfileirar. O log registra delivery ID e motivo, nunca o segredo. Métricas de falhas podem indicar ataque ou rotação incompleta. O critério é reproduzível e testável com vetores oficiais.