Webhooks are a powerful way to receive real-time updates from GoFreight FMS. However, they can also be vulnerable to attacks or unauthorized access if not properly secured. One common method to secure webhooks is by using HMAC (Hash-based Message Authentication Code) signatures. This article will show you how to use HMAC signatures to verify the authenticity of webhook requests from GoFreight.

How to retrieve the secret token?

When you create a webhook subscription via API1, you will be given an auto-generated secret in the response (an example is shown below). You can also retrieve the secret of an existing subscription by sending a GET request to the endpoint /api/v1/webhook/{ref}/2.

{
    "data": {
        "ref": "926a3c25-d1e2-4ee6-a303-405a66ede284",
        "callback_url": "https://example.com/callback/",
        "event_types": ["INVOICE_BLOCK_STATUS_UPDATED"],
        "secret": "Tr5Tkf8wRHsvWiZt",
        "description": "foobar",
        "enabled": true,
        "created_at": "2023-09-08T09:51:42.899365Z",
        "updated_at": "2023-09-08T09:51:42.899336Z"
    }
}

The secret token is used to generate the HMAC signature for each webhook event payload, which will be explained in the next section.

Validate Event Payload from GoFreight

GoFreight uses the secret token to create a HMAC signature with SHA-256 algorithm for each webhook event payload. The signature is included in the x-gofreight-signature header of each webhook request. To verify that if the event payload is from GoFreight, you’ll need to follow these steps:

  1. Retrieve the webhook subscription by the reference ID included in the x-gofreight-webhook-subscription-ref header of the webhook event request.
  2. Retrieve the secret token of the webhook subscription.
  3. Parse the event payload from the request body.
  4. Generate a signature using the secret token and the event payload.
  5. Compare the generated signature with the signature from the request header.

Your language and server implementations might vary from the following examples. Nevertheless, it’s crucial to highlight several key points:

  • GoFreight provides the x-gofreight-signature header values in the format of {timestamp}.{hashed_payload}, where the timestamp is used to prevent replay attacks. You can optionally drop the request if the timestamp is too old (e.g. older than 5 minutes).
  • Using equality operators (e.g. ==) for comparing signatures is not recommended. Use JavaScript’s crypto.timingSafeEqual or Python’s hmac.compare_digest instead to reduce the risk of timing attacks.

Here are some examples of how to verify the signature in different languages: