Check the webhook signatures
Verify the events that BLOOCK sends to your webhook endpoints.
BLOOCK signs the webhook events it sends to your endpoints by including a signature in each event's Bloock-Signature
header. This allows you to verify that the events were sent by BLOOCK, not by a third party.
Before you can verify signatures, you need to retrieve your endpoint's signing secret from your Dashboard's Webhook's settings. Select an endpoint that you want to obtain the secret for, then click the Click to reveal button.
BLOOCK generates a unique secret key for each endpoint. If you use multiple endpoints, you must obtain a secret for each one you want to verify signatures on. After this setup, Bloock starts to sign each webhook it sends to the endpoint.
Preventing replay attacks
A replay attack is when an attacker intercepts a valid payload and its signature, then re-transmits them. To mitigate such attacks, BLOOCK includes a timestamp in the Bloock-Signature
header. Because this timestamp is part of the signed payload, it is also verified by the signature, so an attacker can't change the timestamp without invalidating the signature. If the signature is valid but the timestamp is too old, you can have your application reject the payload.
BLOOCK defines a default tolerance of ten minutes between the timestamp and the current time. You can enable and disable the tolerance control and change this tolerance by changing the number of minutes when verifying signatures.
Verifying signatures using our SDK library
Use our SDK to verify signatures. You perform the verification by providing the event payload, the Bloock-Signature
header, and the endpoint's secret. If verification fails, Bloock returns an error and a false boolean. Remember to import our SDK first.
Bloock requires the raw body of the request to perform signature verification. If you're using a framework, make sure it doesn't manipulate the raw body. Any manipulation to the raw body of the request causes the verification to fail.
- Typescript
- Python
- Golang
import { WebhookClient } from '@bloock/sdk';
import bodyParser from 'body-parser';
import express from 'express';
const app = express();
const port = 3000;
const secretKey = 'NHJTAE6ikKBccSaeCSBSWGdp7NmixXy7';
const options = {
inflate: true,
limit: '100kb',
type: 'application/*',
};
app.use(bodyParser.raw(options));
app.post('/verify', async (req, res) => {
const enforceTolerance = false; // decide if you want to set tolerance when verifying
const body = req.body;
const header = req.get('Bloock-Signature');
const webhookClient = new WebhookClient();
const ok = await webhookClient.verifyWebhookSignature(
body,
header,
secretKey,
enforceTolerance
);
if (!ok) {
console.error('Invalid Signature!');
} else {
console.log('Valid Signature!');
}
return res;
});
app.listen(port, () => {
console.log(`Example app listening on port ${port}`);
});
from flask import Flask
from flask import request
from bloock.client.webhook import WebhookClient
app = Flask(__name__)
SECRET_KEY = "NHJTAE6ikKBccSaeCSBSWGdp7NmixXy7"
@app.route('/verify', methods=['POST'])
def index():
enforce_tolerance = False # decide if you want to set tolerance when verifying
body = request.data
bloock_signature = request.headers['Bloock-Signature']
webhook_client = WebhookClient()
ok = webhook_client.verify_webhook_signature(
body, bloock_signature, SECRET_KEY, enforce_tolerance)
if not ok:
raise ValueError('Invalid Signature!')
else:
print('Valid Signature!')
return 'Finish'
app.run(host='0.0.0.0', port=81)
package main
import (
"io"
"log"
"net/http"
"github.com/bloock/bloock-sdk-go/v2/client"
)
// SecretKey represents the client secret key associate to your webhook endpoint
const SecretKey = "NHJTAE6ikKBccSaeCSBSWGdp7NmixXy7"
func main() {
verifyHandler := func(w http.ResponseWriter, req *http.Request) {
enforceTolerance := false // decide if you want to set tolerance when verifying
body, err := io.ReadAll(req.Body)
if err != nil {
log.Fatalf("Cannot read body request: %v", err)
}
bloockSignature := req.Header.Get("Bloock-Signature")
webhookClient := client.NewWebhookClient()
ok, err := webhookClient.VerifyWebhookSignature(body, bloockSignature, SecretKey, enforceTolerance)
if err != nil {
log.Fatal(err)
}
if !ok {
log.Fatal("Invalid Signature!")
}
log.Println("Valid Signature!")
}
http.HandleFunc("/verify", verifyHandler)
log.Println("Listing for requests at http://localhost:8000/verify")
log.Fatal(http.ListenAndServe(":8000", nil))
}