Segurança
O seu endpoint de webhook fica exposto na internet, e qualquer um pode fazer um POST
nele. Sem validação, alguém poderia forjar um contract.installment.paid e provocar uma
baixa indevida no seu financeiro.
A Quyta assina cada entrega para que você consiga distinguir o que é legítimo.
Como funciona a assinatura
Ao criar a assinatura de webhook no painel, você define um segredo — uma string que só a Quyta e o seu sistema conhecem.
A cada entrega, a Quyta calcula o HMAC SHA-256 do corpo da requisição usando esse segredo e envia o resultado, em hexadecimal, no header:
Code
Seu endpoint recalcula o mesmo HMAC sobre o corpo recebido. Se os valores baterem, a mensagem veio da Quyta e não foi alterada no caminho.
O header só é enviado se a assinatura tiver um segredo configurado. Configure um. Sem ele, não há como distinguir um webhook legítimo de um forjado.
Duas regras que não podem ser quebradas
1. Assine o corpo bruto, não o JSON reserializado.
O HMAC é calculado sobre os bytes exatos que trafegaram. Se o seu framework fizer o parse do JSON e você reserializá-lo para calcular a assinatura, a ordem das chaves, os espaços e o escape de caracteres podem mudar — e a validação falha sempre. Capture o corpo cru antes de qualquer parse.
2. Compare em tempo constante.
Comparar strings com == vaza, pelo tempo de execução, quantos caracteres iniciais
coincidem — o que permite descobrir a assinatura correta byte a byte. Use a função de
comparação segura da sua linguagem.
Implementações
Node.js (Express)
Code
PHP (Laravel)
Code
Python (Flask)
Code
Cuidados com o segredo
- Guarde-o em variável de ambiente ou cofre de segredos, nunca no código-fonte.
- Use segredos diferentes por ambiente. O segredo de homologação não deve validar nada em produção.
- Gere-o com aleatoriedade criptográfica e comprimento razoável — 32 bytes em hexadecimal é uma escolha segura.
- Ao rotacioná-lo, aceite temporariamente as duas assinaturas: valide contra o segredo antigo e o novo enquanto a troca não se completa no painel.
Camadas adicionais
A assinatura é a defesa principal, mas somam-se a ela:
Exija HTTPS. A URL cadastrada deve ser https://, com certificado válido — sem isso,
o corpo do webhook trafega em claro.
Filtre pelo User-Agent. Todas as entregas chegam com Quyta-Webhook-Signature e
User-Agent: Quyta-Webhooks. É um filtro barato para descartar ruído no WAF, mas
não é autenticação: qualquer um pode forjar um header. A validação real é o HMAC.
Use uma URL não adivinhável. Um caminho com um componente aleatório
(/webhooks/quyta/a7f3e1c9) reduz o volume de varredura automatizada que chega ao seu
endpoint. Também é defesa em profundidade, não substituto da assinatura.
Não confie em data para autorizar. Um evento diz o que aconteceu; ele não é
autorização para uma operação irreversível. Antes de uma baixa contábil de valor
relevante, vale confirmar o estado com GET /debts/{id}.

