Skip to Content
TutorialsHow to Authenticate Webhook Payloads

How to Authenticate Webhook Payloads

Welcome to the documentation for how to authenticate webhook payloads sent from Reflex. This feature allows you to securely receive webhook events by validating requests using a webhook secret.

Overview

Webhook secrets provide a way to verify that incoming webhook requests really originate from Reflex. Each team has a unique webhook_secret that is used for signing webhook events.

When an event is triggered, Reflex sends a POST request to the configured webhook URL with an Amboss-Secret header. This header contains an HMAC-SHA256 signature of the webhook payload, signed using the webhook_secret.

Retrieving Webhook Secret

To validate webhook requests, you need your webhook_secret. You can retrieve it using the following GraphQL query or directly in the settings view in Reflex.

Reflex Dashboard

Webhook Settings

GraphQL API

Please note that the Reflex GraphQL API is available at https://reflex.amboss.tech/graphql.

query Team { getUser { team { webhook_secret } } }

Example Response

{ "data": { "getUser": { "team": { "webhook_secret": "df21d54f-618a-4dce-b796-be1ea0ee6716" } } } }

Validating Webhook Requests

To verify the authenticity of incoming webhooks:

  1. Ensure that the Amboss-Secret header is present in the request and retrieve it.
  2. Compute an HMAC-SHA256 hash of the request payload using your webhook_secret.
  3. Compare the computed hash with the Amboss-Secret header value sent by Reflex.

How to Compute the Hash

Example in JavaScript

const crypto = require("crypto"); function computeHash(webhook_payload, webhook_secret) { const hash = crypto .createHmac("sha256", webhook_secret) .update(Buffer.from(JSON.stringify(webhook_payload), "utf8")) .digest("hex") .toLowerCase(); return hash; }

Example in Python

import hmac import hashlib import json def computeHash(webhook_payload, webhook_secret): hash = hmac.new(webhook_secret.encode("utf-8"), msg=bytes(json.dumps(webhook_payload), "utf-8"), digestmod=hashlib.sha256).hexdigest().lower() return hash

These example functions computeHash() performs the following tasks:

  • Generating an HMAC-SHA256 hash of the received payload using your webhook_secret.
  • Encoding the payload consistently by converting it into a UTF-8 JSON string before hashing.
  • Returning the final hash at the end.
  • After this, we can compare the obtained hash with the received Amboss-Secret header value for validating it.

If both hashes match, the webhook is verified as authentic. Otherwise, the request should be rejected as it might have been altered or sent by an unauthorized source.

Example

You can use this example to validate your hashing logic.

Webhook Secret

df21d54f-618a-4dce-b796-be1ea0ee6716

Webhook Payload

{ event: "WORKFLOW_RESULT", payload: { workflow_run_id: "12345", template: { id: "temp_987", name: "Data Processing Workflow", description: "Processes incoming data and generates reports.", }, created_at: "2024-02-12T10:15:30Z", finished_at: "2024-02-12T10:45:00Z", status: "COMPLETED", jobs: [ { id: "job_001", created_at: "2024-02-12T10:16:00Z", finished_at: "2024-02-12T10:30:00Z", job_name: "Data Ingestion", status: "SUCCESS", }, ], inputs: [ { input_name: "dataset_url", value: "https://example.com/dataset.csv", }, ], }, };

Computed HMAC-SHA256 Hash

8548e12b87d55549d2ef9c1f11e4afe00c56ccbd1528fa4a2d654fd6ef998609

Checks

  • This computed hash should be compared with the value of the Amboss-Secret header.
  • If both of the values matches, it confirms that the request is authentic and unaltered, ensuring that it was sent by Reflex and not modified in transit.
  • If they do not match, the request should be rejected as it may have been tampered with or sent by an unauthorized source.

Troubleshooting

⚠️

The HMAC signature is tied to the exact byte sequence of the request body. During parsing, seemingly minor changes—like adjusting the encoding, reformatting JSON, or removing whitespace—can alter this sequence. Even if the content’s meaning remains the same, the byte-level data is modified, leading to a different HMAC signature and ultimately causing Signature Verification to fail.

Last updated on