This page describes by example how you validate the signature of incoming requests
Algorithm
To allow you to validate incoming events, we are signing every request with a signature as part of the header field X-Monta-Signature
.
The value has the following format: sha1={signature}
The signature is generated using this algorithm: HMAC-SHA1 with your webhookSecret
as key (Bytes) and the request body as input.
Example
Given you have set the following secret for your Webhook config: top-secret
And assuming we are sending this (simplified) payload (Post Body): {"foo": "bar"}
We would generate this signature: sha1=d7f7fb0093470143a57bc39a3d9f0bb61fa67131
and deliver it in the header (X-Monta-Signature
).
Generating the signature (Kotlin)
val secret = "top-secret"
val payload = "{\"foo\": \"bar\"}".toByteArray()
val signature = SignRequest.generateSignature(secret, payload)
val expectedSignature = "sha1=d7f7fb0093470143a57bc39a3d9f0bb61fa67131"
expectThat(signature).describedAs("Signatures should match").isEqualTo(expectedSignature)
// Used Methods with outputs
SIGNATURE_ALGORITHM = "HmacSHA1"
SIGNATURE_PREFIX = "sha-1"
// key = "top-secret", payload = [123, 34, 102, 111, 111, 34, 58, 32, 34, 98, 97, 114, 34, 125]
fun generateSignature(key: String, payload: ByteArray): String {
val signingKey = SecretKeySpec(key.toByteArray(), SIGNATURE_ALGORITHM) // key.toByteArray = [116, 111, 112, 45, 115, 101, 99, 114, 101, 116]
val hmac = Mac.getInstance(SIGNATURE_ALGORITHM)
hmac.init(signingKey)
// hmac.doFinal(payload) = [-41, -9, -5, 0, -109, 71, 1, 67, -91, 123, -61, -102, 61, -97, 11, -74, 31, -90, 113, 49]
// hmac.doFinal(payload).toHexString() = "d7f7fb0093470143a57bc39a3d9f0bb61fa67131"
return SIGNATURE_PREFIX + hmac.doFinal(payload).toHexString() // "sha1=d7f7fb0093470143a57bc39a3d9f0bb61fa67131"
}
// converts ByteArray to Hex String
private fun ByteArray.toHexString(): String {
val formatter = Formatter()
for (b in this) {
formatter.format("%02x", b)
}
return formatter.toString()
}