Skip to main content

Check signatures

Blockfrost signs the webhook events it sends to your endpoints. The signature is included in a request Blockfrost-Signature header. This allows you to verify that the events were sent by Blockfrost, not by a third party. You can verify signatures either using our official SDKs, or manually using your own solution.

Before you can verify signatures, you need to retrieve your webhook authentication token from your Secure Webhook settings.

Using SDK

The fastest way to verify the webhook signature is to use built-in helper function from Blockfrost SDKs.

const express = require("express");
const blockfrost = require("@blockfrost/blockfrost-js");
const { verifyWebhookSignature, SignatureVerificationError } = blockfrost;

// You will find your webhook secret auth token in your webhook settings in the Blockfrost Dashboard
const SECRET_AUTH_TOKEN = 'WEBHOOK-AUTH-TOKEN';

const app = express();

app.post('/webhook', express.json({ type: "application/json" }), (request, response) => {
// Validate the webhook signature
const signatureHeader = request.headers["blockfrost-signature"];
try {
const event = verifyWebhookSignature(
JSON.stringify(request.body), // Stringified request.body (Note: In AWS Lambda you don't need to call JSON.stringify as event.body is already stringified)
signatureHeader,
SECRET_AUTH_TOKEN,
600 // Optional param to customize maximum allowed age of the webhook event, defaults to 600s
);

// Signature is valid, process the event
} catch (error) {
// In case of invalid signature verifyWebhookSignature will throw SignatureVerificationError
// for easier debugging you can access passed signatureHeader and webhookPayload values (error.detail.signatureHeader, error.detail.webhookPayload)
console.error(error);
return response.status(400).send("Signature is not valid!");
}

}

app.listen(6666, () => console.log("Running on port 6666"));

Verifying the signature manually

Blockfrost-Signature header contains an unix timestamp with the time of firing the request (prefixed by t=) and a signature (prefixed by schema version, currently v1=).

Signature itself (part after v1=) is created by concatenating:

  • The unix timestamp (as a string)
  • The character .
  • The request JSON payload

Then HMAC with the SHA256 hash function is computed. The concatenated string is used as a message.

Blockfrost-Signature header example:

t=1648550558,v1=162381a59040c97d9b323cdfec02facdfce0968490ec1732f5d938334c1eed4e

Although it is recommended to use our SDKs to verify webhook event signatures, you can create a custom solution by following these steps.

1. Parse the timestamp and signature from the header

Split the header, using the , character as the separator, to get a list of elements. Then split each element, using the = character as the separator, to get a key-value pair.

The value for the key t corresponds to the timestamp, and the value after v1 corresponds to the signature. The header may contain multiple signatures with the same version schema.

2. Prepare the signature_payload

Prepare the signature_payload by concatenating:

  • The unix timestamp (as a string)
  • The character .
  • The request JSON payload

3. Compute the expected signature

Compute an HMAC with the SHA256 hash function. Use the webhook authentication token as the key, and use the prepared signature_payload string as the message.

4. Compare the signatures

Compare the computed signature with signatures extracted from the Blockfrost-Signature. If one of the signatures extracted from Blockfrost-Signature matches the computed signature, then compute the difference between the current timestamp and the received timestamp and decide if the difference is within your tolerance. By default, the Blockfrost SDK considers the signature valid if the difference is less than 10 minutes (600 seconds). If none of the signatures in Blockfrost-Signature header matches the computed signature, or if the difference between the timestamps is larger than the tolerance, the signature is considered invalid.