Skip to main content

Webhook integration

Validate webhook notification signature

If HMAC is generated while creating a webhook - which is strongly advised - a signature will be generated and included in the payload for each notification. This allows integrators to validate that the request comes from Enviso, and has not been tampered with before processing it.

Procedure to verify the signature:
  1. Concatenate the values for id, tenant, event, and timestamp in the format id|tenant|event|timestamp

  2. Create a SHA256 hash of this concatenated value.

  3. Compare this value with the signature of the payload. If they are equal, then the notification can be considered valid, and the notification can be processed.

Sample code for C# .Net

Sample code that demonstrates how to generate a signature of the notification payload.

using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Text;
using System;

public static class Generator
{
    private const string SignaturePayloadSeparator = "|";
    private const string HmacKey = "<HMAC key>"; // Hmac key which was generated while creating webhook

    public static void Main(string[] args)
    {
        var notificationId ="<notification id>"; // 'id' from response payload
        var tenantkey = "<tenant key>"; // 'tenant' from response payload
        var eventName = "<event name>"; // 'event' from response payload
        var timestamp = "<timestamp>"; // 'timestamp' from response payload

        var payload = CreateSignaturePayload(notificationId, tenantkey, eventName, timestamp);
        var signature = CreateSignature(payload);
        Console.WriteLine($"signature is : {signature}");
    }

    private static string CreateSignaturePayload(string notificationId, string tenant, string eventName, string timestamp)
    {
        var interpolatedStringHandler = new DefaultInterpolatedStringHandler(3, 4);
        interpolatedStringHandler.AppendFormatted(notificationId);
        interpolatedStringHandler.AppendLiteral(SignaturePayloadSeparator);
        interpolatedStringHandler.AppendFormatted(tenant);
        interpolatedStringHandler.AppendLiteral(SignaturePayloadSeparator);
        interpolatedStringHandler.AppendFormatted(eventName);
        interpolatedStringHandler.AppendLiteral(SignaturePayloadSeparator);
        interpolatedStringHandler.AppendFormatted(timestamp);
        return interpolatedStringHandler.ToStringAndClear();
    }

   public static string CreateSignature(string payload)
    {
        // Convert the HEX key to a byte array that can be used as key for HMACSHA256
        var key = Encoding.UTF8.GetBytes(HmacKey);

        // Convert the payload to byte array that can be used as input to compute the hash
        var buffer = Encoding.UTF8.GetBytes(payload);

        // Create new HMACSHA256 object and compute the hash
        using var hmac = new HMACSHA256(key);
        var hash = hmac.ComputeHash(buffer);

        // First pass base64 encodes the digest; the second encodes the utf8 bytes of that string. The second pass
        // was previously done for us by the json serializer when it wrote the byte[] this method used to return -
        // it is spelled out here so the value is complete before it reaches the body and the header. See remarks.
        return Convert.ToBase64String(Encoding.UTF8.GetBytes(Convert.ToBase64String(hash)));
    }

}

Sample test notification payload

{
  "id": "8172849c-e676-4c2a-8be8-2824cf41efa0",
  "tenant": "********",
  "event": "ORDER_CREATED",
  "timestamp": "2023-08-11T14:09:41.933Z",
  "data": {
    "id": "test"
  },
  "signature": "K0Z4V2lkM2pIaHpZdUNES3ZPRHJhcWNIaVFIN1R1SXpuZUgvSXBmMUtEQT0="
}

Sample real notification payload

{
  "id": "8172849c-e676-4c2a-8be8-2824cf41efa0",
  "tenant": "**********",
  "event": "ORDER_CREATED",
  "timestamp": "2023-08-11T14:09:41.933Z",
  "data": {
    "id": "1001"
  },
  "signature": "K0Z4V2lkM2pIaHpZdUNES3ZPRHJhcWNIaVFIN1R1SXpuZUgvSXBmMUtEQT0="
}