Webhooks Authentication
Duda can sign requests using the HMAC-SHA256 algorithm to allow your app to verify the authenticity of the sender (Duda) and of the payload.
This feature is available only for managed accounts
To get access to this feature, please contact your account manager or Duda support.
Signature generation and decoding
The signature value is calculated as follows:
-
Signature = base64(hmac-sha256(secret-key, timestamp + "." + message))
-
Where
timestamp
is the value of thex-duda-signature-timestamp
request header. -
message
is the actual request body. -
"."
is a string separating the 2 values. -
secret-key
your unique key you received from Duda, decoded using base64 and UTF-8.
This calculation is done by Duda and the value is added to the webhook in the x-duda-signature
request header.
The same calculation should be made by the application and compared against the header to assert the message was signed by us using your secret key.
An example with data
The request body is {'key1':'world','key2':'world'}
the timestamp (x-duda-signature-timestamp
header) is 1570350275357
and our secret key is mysecretsecret
.
Calculating base64(hmac-sha256(secret-key, timestamp + "." + message))
results in +DCfT1wIMUiaZnlZB4u59/d5wkXKA89lv67Ov66vnyc=
which is the value we will find in x-duda-signature
header of the signed request.
Code examples
String getHMAC(String timestamp,String message) {
String secretKey = ...;
SecretKeySpec signingKey = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
String input = timestamp + "." + message;
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(signingKey);
byte[] rawHmac = mac.doFinal(input.getBytes(StandardCharsets.UTF_8));
return new String(Base64.getEncoder().encode((rawHmac)));
}
String body = request.getBody();
String timestamp = request.getHeader("x-duda-signature-timestamp");
String hmac = getHMAC(timestamp, body);
String signautreHeader = request.getHeader("x-duda-signature");
assert hmac.equals(signautreHeader);
const crypto = require('crypto');
const sig = req.headers["x-duda-signature"];
const time = req.headers["x-duda-signature-timestamp"];
const body = JSON.stringify(req.body);
const decoded = Buffer.from(<secret-key>, "base64").toString("utf8");
const check = crypto.createHmac("sha256", decoded)
.update(`${time}.${body}`)
.digest("base64");
assert(sig === check);
Updated 3 months ago