Validating Events Sent By Envase Connect
Webhook Event Publish Diagram
Envase Connect uses a static IP address and HMAC256 signature header that consumers can use to verify the authenticity of the event received.
X-Envase-Connect-Signature-256 Header and Authenticity
The X-Envase-Connect-Signature-256 header is created by concatenating the following:
UTC timestamp
A comma
The signed payload
Below is an example of a complete header (new lines have been added to help with readability):
X-Envase-Connect-Signature-256=
t=1492774577,
v1=eb6bcee763697846d201883b40719be2631518d1a23487e0073c43e74004653
The signed payload string is created by concatenating: - The timestamp -
The period character [.]
- The actual JSON payload (i.e., the
request body)
Below is an example of a full signed payload:
1492774577.{event}
Create a Signing Key
Your signing key is used to sign the X-Envase-Connect-Signature-256
for each event we send to your endpoint. To create a valid signing key,
use a random high entropy string (e.g., by taking the output of
ruby -rsecurerandom -e "puts SecureRandom.hex(20)"
at the terminal).
Once a signing key has been created, set the signing key property when creating a webhook using the “signingKey” property, as in the example below:
{
"url": "https://your-domain.com/some-endpoint",
"triggers": [
"APPROVED",
"REJECTED"
],
"entityType": "GATE",
"signingKey": "your-signing-key"
}
Be sure to store your signing key in a secure location as it will need to be retrieved in the future to verify the signature header of events you receive.
Warning
There is no way to retrieve a previously set signing key. If you lose your signing key, you will need to create a new one and update your webhooks with it.
When your signing key is set, Envase Connect uses it to create a hash
signature with each payload. This hash signature is included with the
headers of each request as X-Envase-Connect-Signature-256
.
Verify X-Envase-Connect-Signature-256
To verify the X-Envase-Connect-Signature-256 do the following steps:
Parse the X-Envase-Connect-Signature-256 header getting the UTC timestamp
(t)
and signed payload.Compute an HMAC with the SHA256 hash function. The output of the SHA256 hash should be hex encoded. Use your webhook’s signing key as the key, and the message should be
{timestamp}.{event}
.Compare the signature in the header to the expected signature
(v1)
Node Tyepscript example to create HMAC 256 hash example using
crypto-js
npm package:
import * as crypto from 'crypto-js';
const hmac256Hash: string = crypto.enc.Hex.stringify(
crypto.HmacSHA256(
`${utcTimestamp}.${JSON.stringify(event)}`,
YOUR_WEBHOOK_SIGNING_KEY
)
);
Example
Let’s say that the event looks like the following:
{
"action": "SHOWING",
"type": "EXAMPLE",
"payload": {
"id": "123Test",
"info": "Example data"
}
}
The signing key that you created with your webhook is
R$4m726fYFo{d7w4
.
The event came with the header:
"X-Envase-Connect-Signature-256": "t=1660929593448,v1=8506bcdc106d9db53eba0dfbbcc14c4ad2ce9c89783747d58807ad565747243c"
You will then take the event and parse it as a string to get the result:
"{"action":"SHOWING","type":"EXAMPLE","payload":{"id":"123Test","info":"Example data"}}"
The message to encode is then:
"1660929593448.{"action":"SHOWING","type":"EXAMPLE","payload":{"id":"123Test","info":"Example data"}}"
And if you run the following code from the example above:
import * as crypto from 'crypto-js';
const hmac256Hash: string = crypto.enc.Hex.stringify(
crypto.HmacSHA256(
"1660929593448.{"action":"SHOWING","type":"EXAMPLE","payload":{"id":"123Test","info":"Example data"}}",
"R$4m726fYFo{d7w4"
)
);
You would then compare the value of hmac256Hash
to the value in the
signature header labeled v1=
which in this case is,
8506bcdc106d9db53eba0dfbbcc14c4ad2ce9c89783747d58807ad565747243c
.
If they match, it is an authentic message from our system.
Note
If using a website such as https://www.devglan.com/online-tools/hmac-sha256-online to verify the hash, make sure the selected output type is in Hex format and remove the leading and trailing quotations. So the values would look like this:
1660929593448.{"action":"SHOWING","type":"EXAMPLE","payload":{"id":"123Test","info":"Example data"}}
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, Envase
includes a timestamp in the X-Envase-Connect-Signature-256
header.
Because this timestamp is part of the signed payload, it is also
verified by the signature, so an attacker cannot 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.