Due to the nature of webhooks, attackers can impersonate services by simply sending a fake webhook to an endpoint. Consider this: it’s merely an HTTP POST from an unknown source. This poses a potential security risk for many applications, or at the very least, a source of issues.
In order to prevent this, ChatBrick signs each webhook and its metadata with a unique key for each endpoint. This signature can then be used to verify that the webhook indeed comes from ChatBrick, and it should only be processed if this is the case.
Another potential security risk is what’s known as replay attacks. A replay attack occurs when an attacker intercepts a valid payload (including the signature) and re-transmits it to your endpoint. This payload will pass signature validation and will therefore be acted upon.
To mitigate this attack, ChatBrick includes a timestamp for when the webhook attempt occurred. Our libraries automatically reject webhooks with a timestamp that is more than five minutes away (past or future) from the current time. This requires your server’s clock to be synchronized and accurate, and it’s recommended that you use NTP to achieve this.
Then, verify the webhook event using the code below. The payload is the raw (string) body of the request, and the headers are the headers passed in the request.
Copy
import { Webhook } from "svix";// The secret is unique to each endpoint// Yoy can retrieve it from the ChatBrick dashboardconst secret = "whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw";// These were all sent from the ChatBrick serverconst headers = { "svix-id": "msg_p5jXN8AQM9LWM0D4loKWxJek", "svix-timestamp": "1614265330", "svix-signature": "v1,g0hM9SsE+OTPJTGt/tmIKtSyZlE3uFJELVlNIOLJ1OE=",};// The payload is the raw JSON string sent by ChatBrick// Please note that the payload should be the raw request body, not a parsed JSON object.const payload = '{"test": 2432232314}';const wh = new Webhook(secret);// Throws on error, returns the verified content on successconst payload = wh.verify(payload, headers);
First install the library using your package manager of choice:
Then, verify the webhook event using the code below. The payload is the raw (string) body of the request, and the headers are the headers passed in the request.
Copy
import { Webhook } from "svix";// The secret is unique to each endpoint// Yoy can retrieve it from the ChatBrick dashboardconst secret = "whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw";// These were all sent from the ChatBrick serverconst headers = { "svix-id": "msg_p5jXN8AQM9LWM0D4loKWxJek", "svix-timestamp": "1614265330", "svix-signature": "v1,g0hM9SsE+OTPJTGt/tmIKtSyZlE3uFJELVlNIOLJ1OE=",};// The payload is the raw JSON string sent by ChatBrick// Please note that the payload should be the raw request body, not a parsed JSON object.const payload = '{"test": 2432232314}';const wh = new Webhook(secret);// Throws on error, returns the verified content on successconst payload = wh.verify(payload, headers);
Copy
dotnet add package Svix
Copy
using Svix;using System.Net;// These were all sent from the ChatBrick servervar headers = new WebHeaderCollection();headers.Set("svix-id", "msg_p5jXN8AQM9LWM0D4loKWxJek");headers.Set("svix-timestamp", "1614265330");headers.Set("svix-signature", "v1,g0hM9SsE+OTPJTGt/tmIKtSyZlE3uFJELVlNIOLJ1OE=");// The payload is the raw JSON string sent by ChatBrick// Please note that the payload should be the raw request body, not a parsed JSON object.var payload = "{\"test\": 2432232314}";// The secret is unique to each endpoint// Yoy can retrieve it from the ChatBrick dashboardvar wh = new Webhook("whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw/Je4ZJEGP1QFb");// Throws on errorwh.Verify(payload, headers);
Copy
implementation "com.svix:svix:0.x.y"
Copy
import com.svix.Webhook;// The secret is unique to each endpoint// Yoy can retrieve it from the ChatBrick dashboardString secret = "whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw";// These were all sent from the ChatBrick serverHashMap<String, List<String>> headerMap = new HashMap<String, List<String>>();headerMap.put("svix-id", Arrays.asList("msg_p5jXN8AQM9LWM0D4loKWxJek"));headerMap.put("svix-timestamp", Arrays.asList("1614265330"));headerMap.put("svix-signature", Arrays.asList("v1,g0hM9SsE+OTPJTGt/tmIKtSyZlE3uFJELVlNIOLJ1OE="));HttpHeaders headers = HttpHeaders.of(headerMap, BiPredicate<String, String>)// The payload is the raw JSON string sent by ChatBrick// Please note that the payload should be the raw request body, not a parsed JSON object.String payload = "{\"test\": 2432232314}";Webhook webhook = new Webhook(secret);webhook.verify(payload, headers)// throws WebhookVerificationError exception on failure.
Copy
composer require svix/svix
Copy
// import using composers autoloadrequire_once('vendor/autoload.php');// or manuallyrequire_once('/path/to/svix/php/init.php');// These were all sent from the ChatBrick server$header = array( 'svix-id' => 'msg_p5jXN8AQM9LWM0D4loKWxJek', 'svix-timestamp' => '1614265330', 'svix-signature' => 'v1,g0hM9SsE+OTPJTGt/tmIKtSyZlE3uFJELVlNIOLJ1OE=',);// The payload is the raw JSON string sent by ChatBrick// Please note that the payload should be the raw request body, not a parsed JSON object.$payload = '{"test": 2432232314}';// The secret is unique to each endpoint// Yoy can retrieve it from the ChatBrick dashboard$wh = new \Svix\Webhook('whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw');// Throws on error, returns the verified content on success$json = $wh->verify($payload, $header);
To use the Svix library in this language, you can follow the instructions provided in the Svix documentation.
To use the Svix library in this language, you can follow the instructions provided in the Svix documentation.
To use the Svix library in this language, you can follow the instructions provided in the Svix documentation.
To use the Svix library in this language, you can follow the instructions provided in the Svix documentation.
To use the Svix library in this language, you can follow the instructions provided in the Svix documentation.