Assinatura de webhook
Toda entrega leva uma assinatura HMAC-SHA256. Ela prova que a requisição veio da owiew e que o corpo não foi alterado. A verificação é obrigatória: um receptor que não verifica aceita qualquer pessoa que descubra a URL.
O que é assinado
Seção intitulada “O que é assinado”assinatura = hex_minusculo( HMAC-SHA256( segredo, X-Owiew-Timestamp + "." + corpo_bruto ) )segredoé o segredo da inscrição, mostrado uma única vez na criação.X-Owiew-Timestampé o texto do cabeçalho, em segundos, sem espaço.corpo_brutosão os bytes exatos recebidos. Não decodifique e reserialize o JSON antes de verificar: qualquer diferença de espaço ou ordem de campos muda a assinatura.
O cabeçalho X-Owiew-Signature tem o formato v1=<hex>. A parte v1 é a versão do esquema.
Algoritmo de verificação
Seção intitulada “Algoritmo de verificação”- Leia o corpo como bytes, com limite de 256 KiB.
- Leia
X-Owiew-Timestamp. Se não for um inteiro, recuse. - Compare com o seu relógio. Se a diferença passar de 5 minutos, para mais ou para menos, recuse. Isso barra a reapresentação de uma requisição antiga capturada por terceiros.
- Para cada segredo válido, calcule a assinatura esperada.
- Separe
X-Owiew-Signaturepor vírgula, mantenha as partes que começam comv1=e compare cada uma com cada esperada em tempo constante (timingSafeEqualem Node,hmac.Equalem Go). Aceite se qualquer par conferir. - Se nada conferir, responda
401sem explicar o motivo. - Só depois de verificar, interprete o JSON e aplique a idempotência por
X-Owiew-Delivery-Id.
Mantenha o relógio do servidor sincronizado (NTP). Relógio fora de hora faz entregas legítimas serem recusadas e dispara repetições.
Tolerância de relógio e repetição
Seção intitulada “Tolerância de relógio e repetição”A cada tentativa de entrega, a owiew calcula um timestamp novo e assina de novo. Uma repetição minutos depois da primeira falha tem timestamp novo e passa na janela de 5 minutos. O X-Owiew-Delivery-Id continua o mesmo, e é ele que você usa para deduplicar. A janela de tempo limita a reapresentação de uma captura antiga, e a deduplicação por identificador limita a reapresentação dentro da janela. Use as duas.
Rotação de segredo
Seção intitulada “Rotação de segredo”Quando o segredo é rotacionado, o anterior continua valendo por 24 horas. Nesse período cada entrega leva duas assinaturas, a do segredo novo primeiro:
X-Owiew-Signature: v1=<assinatura com o segredo novo>, v1=<assinatura com o segredo antigo>Aceite a entrega se qualquer assinatura conferir com qualquer segredo que você tenha. O roteiro seguro:
- Peça a rotação. O segredo novo é mostrado uma única vez.
- Coloque o segredo novo no cofre e deixe o antigo ao lado dele.
- Faça o deploy do receptor que aceita os dois.
- Passadas as 24 horas, remova o antigo.
Vetor de teste
Seção intitulada “Vetor de teste”Use este vetor para validar a sua implementação. Os valores são de exemplo.
| Item | Valor |
|---|---|
| Segredo | segredo-de-exemplo |
| Timestamp | 1800000000 |
| Corpo | {"tipo":"instalacao.teste.v1"} |
| Assinatura esperada | v1=328f40657fa58788f8633269a9d7c02fed3dfc84ef8f127f41c9e437fbc46807 |
Texto assinado: 1800000000.{"tipo":"instalacao.teste.v1"}. Calcule o HMAC-SHA256 desse texto com o segredo acima: o resultado precisa ser o valor da tabela. Os testes dos exemplos em Node e Go geram a assinatura pelo mesmo cálculo.
Erros comuns
Seção intitulada “Erros comuns”- Verificar sobre o JSON reserializado, e não sobre os bytes recebidos.
- Comparar com
==em vez de comparação em tempo constante. - Esquecer o ponto entre o timestamp e o corpo.
- Aceitar apenas a primeira assinatura durante a rotação.
- Usar um framework que já consumiu o corpo (middleware de JSON) antes da verificação. Capture o corpo bruto.
- Responder
200antes de verificar.