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.

{/* Go up to top button */}
{/* This is a markdown Font Size Adjust */}