Implement the webhook event signature validation
<HTMLBlock>{`
{/* This is a 6 Columns Layout */}
<div class="info-row">
<div class="info-column1">
<img src="https://assets.2hire.io/Easy.svg"></img>
</div>
<div class="info-column2">
<p style="margin:0px;">Low difficulty</p>
</div>
<div class="info-column3">
<img src="https://assets.2hire.io/Read-5Min.svg"></img>
</div>
<div class="info-column4">
<p style="margin:0px;">5 min read time</p>
</div>
<div class="info-column5">
<img src="https://assets.2hire.io/IMP-15Min.svg"></img>
</div>
<div class="info-column6">
<p style="margin:0px;">15 min implementation time</p>
</div>
</div>
<style>
.info-row {
display: flex;
width:100%;
margin-top:16px;
justify-content:left;
font-size:13px;
}
.info-column1 {
width: 5%;
padding: 0px;
margin:auto;
}
.info-column2 {
width: 16%;
padding: 4px;
margin:auto;
}
.info-column3 {
width: 5%;
margin:auto;
}
.info-column4 {
width: 18%;
padding: 4px;
margin:auto;
}
.info-column5 {
width: 5%;
margin:auto;
}
.info-column6 {
width: 30%;
padding: 4px;
margin:auto;
}
</style>
`}</HTMLBlock>
<br>
## How to validate the signature
When you subscribe to a webhook event to receive signal updates from a vehicle, you will receive POST requests with the `X-Hub-Signature` header.
This header represents the message signature that allows checking the authenticity of the request.
<HTMLBlock>{`
<div class="callout_theme_1">
<p class="callout_text_1">How can we validate it?</p>
</div>
<style>
.callout_theme_1 {
background-color: #F8F8F8;
color: #646464;
padding:16px;
margin:auto;
border-radius:0px 8px 8px 0px;
border-left:4px solid gray;
}
.callout_text_1 {
margin-bottom:0px!important;
font-size:14px;
font-weight:400;
font-style:italic;
}
</style>
`}</HTMLBlock>
We need to check if the signature is the concatenation of two strings separated by the `=` character:
* The first string has to be the name of a hash function for example, `MD5`, `SHA1`, `SHA256` or others. Let us call it **algorithm**.
> 📘 Info
>
> This system currently uses the `SHA256` hash function.
* The second string is the `HMAC` using the hash function named in the first string.\
Let us call it **HMAC(message, secret, algorithm)**.
The signature will have a form like the following:\
`algorithm=HMAC(message, secret, algorithm)`.
> 📘 Info
>
> If you don't remember what we are talking about, please visit the [Receiving signal guide's](https://developer.2hire.io/docs/receiving-signals) page.
<br>
### What is HMAC
In cryptography, an [HMAC](https://en.wikipedia.org/wiki/HMAC) is a specific type of message authentication code, MAC, involving a cryptographic **hash function** and a **secret** cryptographic key.
To validate the `HMAC`, we need to generate it using the following parameters:
* A message that is the body of the POST request we are receiving.
* A secret, that is the ‘hub.secret’ property we used in the body of the request made at the moment of the [webhook subscription](https://developer.2hire.io/docs/receiving-signals#introduction).
* A hash function, which is written in the first string of the signature as explained before.
> 🚧 Warning!
>
> Both the secret and message have to be encoded in `utf-8`.\
> Be careful when parsing the message, the body of the request in our case, because it has to be a text!
<br>
<hr>
## Code
```typescript
import * as crypto from "crypto";
const supportedAlgorithms = ["sha256"];
const isSignatureValid = (message: string, secret: string, signature: string): boolean => {
const parts = signature.split("=");
if (parts.length !== 2) {
return false;
}
const algorithm = parts[0];
if (!supportedAlgorithms.includes(algorithm)) {
return false;
}
const hmac = crypto.createHmac(algorithm, secret)
.update(message, "utf8")
.digest();
const signatureBuffer = Buffer.from(parts[1], "hex");
return crypto.timingSafeEqual(signatureBuffer, hmac);
};
How this example works
If you want to have feedback if you are implementing it in the right way, here we show a practical example of a signature generated from the following parameters:
- Message:
{"topic":"vehicle:7d42d670-6a96-4ff0-ab63-5d6673967d2d:generic:autonomy_meters","payload":{"data":{"meters":24000},"timestamp":1614594977551,"deliveryTimestamp":1614594977563}}
- Secret:
this_is_a_$ecret
. - Hash function:
sha256
.
The generated signature will be: sha256=bb2c166d254838b72bd78b0486d804cef58bd36c987d12147d554b45700e69f4
.
Congrats!Now, you have a simple method to validate a signature.
{/* This is a markdown Font Size Adjust */}
Updated 20 days ago