O header
A assinatura é calculada assim:
Como verificar
1
Leia o corpo bruto
Use os bytes exatamente como chegaram. Se você fizer parse e serializar o JSON de novo, os bytes mudam e a assinatura não confere.
2
Cheque o timestamp
Rejeite a entrega se
t estiver a mais de 5 minutos do horário atual. Isso protege contra reenvio de uma requisição capturada.3
Calcule o HMAC
Calcule o HMAC-SHA256 de
"{t}.{corpo_bruto}" com o secret do endpoint.4
Compare em tempo constante
Compare com cada valor
v1 do header usando uma comparação de tempo constante. Basta um deles conferir.Com o SDK
constructEvent faz tudo isso, não faz chamadas de rede e retorna o evento tipado.
Sem o SDK
Rotação do segredo
Para trocar o segredo sem perder eventos, chamePOST /v1/webhook_endpoints/{id}/rotate_secret. A resposta traz o novo secret.
- Por 24 horas, os dois segredos (o novo e o anterior) assinam as entregas, e o header traz dois valores
v1=. - Durante esse período, valide com os dois segredos. O SDK aceita uma lista:
constructEvent(rawBody, header, [novoSegredo, segredoAnterior]). - Depois da janela, o segredo antigo deixa de valer.
Problemas comuns
A assinatura nunca confere
A assinatura nunca confere
Quase sempre é o corpo: um middleware já fez o parse do JSON e você está usando a serialização dele. Configure seu framework para expor o corpo bruto da rota do webhook (por exemplo
express.raw({ type: 'application/json' })).Funciona em testes, mas falha em produção
Funciona em testes, mas falha em produção
Confirme que você usa o segredo do endpoint certo. Cada endpoint tem o seu. Confirme também que o relógio do servidor está sincronizado, já que a tolerância é de 5 minutos.
Falha logo após rotacionar o segredo
Falha logo após rotacionar o segredo
Valide com o segredo novo e com o anterior até a janela de 24 horas terminar.