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": "0ed52732-3e29-4f51-ba46-5ef0fb06b893" } } } }

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(payload, webhook_secret) { const hash = crypto .createHmac("sha256", webhook_secret) .update(Buffer.from(JSON.stringify(payload), "utf8")) .digest("hex") .toLowerCase(); return hash; }

Example in Python

hash_val = hmac \ .new( api_key.encode('utf-8'), msg=bytes(payload, encoding='utf-8'), digestmod=hashlib.sha256 ) \ .hexdigest() \ .lower() print(hash_val)

This example function verifyWebhook() 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.
  • It returns the final hash.
  • After this, we can compare the obtained hash with the received Amboss-Secret header value.

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.

Amboss Secret Header

0ed52732-3e29-4f51-ba46-5ef0fb06b893

Webhook Payload

const 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

7a1b3851371c4ad8d1218ee3a2f69a64752ad48aafb0360544428c1c16551a16

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