Validating Events Sent By Envase Connect

Webhook Event Publish Diagram

../_images/webhook_security.png

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.