Todos os artigos
Integração · 6 min de leitura

Webhooks de assinatura: eventos e validação HMAC

Webhooks de assinatura eletrônica são notificações HTTP que sua aplicação recebe automaticamente quando algo acontece em um envelope — um documento foi enviado, alguém assinou, o processo terminou. Em vez de ficar consultando a API de tempos em tempos para saber se o cliente já assinou o contrato, seu sistema recebe um POST assim que o evento ocorre e reage na hora: atualiza o status no ERP, libera um pedido, dispara a próxima etapa do fluxo.

A validação HMAC é a parte que garante que esse POST realmente veio do e-Social Sign. Cada entrega chega acompanhada de uma assinatura calculada com um segredo que só você e a plataforma conhecem. Se o seu endpoint checa essa assinatura antes de confiar no payload, qualquer tentativa de forjar um evento cai por terra. Se não checa, o endpoint aceita qualquer POST que chegue na URL certa — e é exatamente esse buraco que este artigo existe para fechar.

O que são webhooks nesse contexto

Ao integrar assinatura eletrônica em um sistema próprio (ERP, CRM, plataforma de vendas), o fluxo típico é: seu backend cria o envelope via API, o e-Social Sign cuida do envio, da coleta de evidências e da assinatura, e devolve o resultado por webhook. Você cadastra uma URL do seu servidor e escolhe quais eventos quer receber — coisas como envelope enviado, signatário assinou, envelope concluído, entre outros do ciclo de vida do documento. A cada evento, a plataforma faz um POST em JSON para essa URL, com o nome do evento e os dados relevantes daquele momento.

Isso evita polling: sem webhook, a única forma de saber que um contrato foi assinado é chamar a API repetidamente até o status mudar. Com webhook, a informação chega no exato momento em que o evento ocorre.

Por que validar a assinatura importa de verdade

Aqui está o ponto central: a URL do seu webhook não é secreta. Ela aparece em logs de proxy, em headers de requisição, pode vazar em uma captura de tela de configuração, em um repositório de infraestrutura, em uma ferramenta de monitoramento. Uma vez que alguém descobre essa URL, nada impede essa pessoa de montar um POST JSON parecido com o de um evento real e mandar direto para o seu endpoint.

Se o seu código só olha para o corpo da requisição — "chegou um JSON com event: envelope.completed, então marco o contrato como assinado no ERP" — esse é exatamente o cenário que um atacante pode reproduzir sem nunca ter tocado no e-Social Sign. Ele não precisa de acesso à sua conta, não precisa saber nada sobre o envelope de verdade: só precisa da URL e de um payload plausível. O resultado prático é grave — um sistema financeiro que libera um pagamento assim que recebe "documento assinado", sem validar de forma independente se aquele documento realmente foi assinado, um pedido que é despachado, um acesso que é concedido, tudo baseado numa notificação forjada.

A assinatura HMAC fecha essa brecha porque ela depende de um segredo que nunca trafega na requisição em si. A entrega inclui um header com essa assinatura, calculada a partir do corpo bruto da requisição usando o secret gerado quando você criou o webhook. Sem conhecer esse secret, é matematicamente inviável produzir uma assinatura que bata com um payload arbitrário. Validar significa: pegar o corpo exatamente como chegou, recalcular o hash com o seu secret, e comparar com o valor recebido. Só se as duas assinaturas coincidirem o evento é confiável.

Como validar sem abrir uma nova falha

Ter a lógica de comparação certa importa tanto quanto ter a lógica de cálculo certa. Uma comparação ingênua de strings (if ($assinaturaCalculada == $assinaturaRecebida)) pode vazar informação por timing attack: o tempo que a comparação leva varia conforme quantos caracteres batem antes de encontrar a diferença, e isso pode, em teoria, ajudar um atacante a descobrir a assinatura correta byte a byte. Por isso a validação deve usar uma função de comparação em tempo constante — em PHP, hash_equals() — que sempre leva o mesmo tempo independentemente de onde as strings divergem.

Em linhas gerais, a validação segue este roteiro:

1. Ler o corpo bruto (raw) da requisição — não o JSON já decodificado
2. Calcular HMAC-SHA256 desse corpo usando o secret do seu webhook
3. Comparar o resultado com a assinatura recebida no header, usando hash_equals()
4. Só processar o evento se a comparação for verdadeira
5. Responder com um status de sucesso (2xx) depois de aceitar a entrega

Um detalhe que costuma passar despercebido: o cálculo precisa usar o corpo exatamente como chegou na rede, byte a byte. Se o seu framework re-serializa o JSON antes de você calcular o hash (por exemplo, decodificando e recodificando o objeto), a ordem das chaves ou espaçamento pode mudar, e a assinatura recalculada não vai bater mesmo sendo uma entrega legítima. A prática segura é capturar o corpo bruto antes de qualquer parsing.

Vale lembrar também que o secret do webhook é exibido uma única vez (na tela de criação/edição) e deve ser guardado com o mesmo cuidado de uma senha de banco de dados — variável de ambiente, cofre de segredos, nunca hardcoded no repositório. Quem tem o secret consegue produzir assinaturas válidas, então ele é, na prática, a credencial que protege esse canal.

Testando a integração antes de ir para produção

Antes de depender de eventos reais chegando via webhook, vale disparar uma entrega de teste contra o seu endpoint para confirmar que ele responde corretamente e que a validação da assinatura está passando com o formato real de entrega. Isso evita descobrir um bug de parsing só quando o primeiro contrato de verdade é assinado. Depois de configurado, acompanhar o histórico de entregas ajuda a diagnosticar rapidamente falhas de timeout, resposta fora do padrão 2xx ou endpoint fora do ar — problemas de infraestrutura, não de assinatura, mas que também derrubam a confiabilidade da integração.

Comece a integrar

Se você está construindo essa integração para um sistema que ainda não usa e-Social Sign, o caminho mais rápido é criar uma conta, gerar um envelope de teste pela API e configurar um webhook de desenvolvimento apontando para um endpoint local (com um túnel HTTPS, por exemplo). Crie sua conta gratuita e comece a testar hoje mesmo.

Pronto para assinar seus documentos?

Crie sua conta grátis e envie o primeiro documento para assinatura ainda hoje.

Criar conta grátis

Continue lendo

Artigos relacionados