Verify webhooks with ngrok’s new Traffic Policy action

Today, we are excited to announce the availability of a new traffic policy action: Verify Webhook. This action verifies that webhook requests sent to your HTTP endpoints originate from your webhook provider and are intended for you. (You may be using our webhook verification module to authenticate webhook requests.)

Now, you can add webhook verification to your applications by adding the following traffic policy rule to your endpoint, substituting the appropriate values for PROVIDER and YOUR_SECRET:

on_http_request:
  - actions:
    - type: verify-webhook
      config:
        provider: PROVIDER
        secret: YOUR_SECRET

How webhooks work

Webhooks enable one application or API to send an HTTP request to another system whenever a specific event occurs, often including a data payload. For instance, a Zoom webhook can automatically trigger updates in a CRM system when a meeting starts or ends, ensuring customer records are updated with meeting details. Since implementing webhooks requires exposing an HTTP endpoint that a third-party system can send requests to, it’s critical to protect this endpoint to avoid forged requests, man-in-the-middle, and replay attacks. 

By authenticating webhook requests, the Verify Webhook traffic policy action protects your application from unauthorized webhooks and protects your webhook provider from various kinds of attacks. 

The Verify Webhook traffic policy action supports over 50 popular webhook providers. With over one hundred ways to cryptographically sign webhook requests, our Verify Webhook traffic policy action implements precise verification logic for each supported provider to validate requests and ensure only authenticated ones reach your backend service. 

Get started verifying webhooks

Let’s go through an example. Applying the following traffic policy rule ensures that only webhook requests originating from Zoom can reach your service. “ngrokrocks” is the secret key we use to validate requests from Zoom.

on_http_request:
  - actions:
      - type: verify-webhook
        config:
          provider: "zoom"
          secret: "ngrokrocks"

You can start an agent endpoint and apply the policy above by saving it to a file and passing it in the following command:

ngrok http 3000 --url=https://example.ngrok.dev --traffic-policy-file=policy.yaml

Once you run this command, ngrok forwards requests that pass validation to https://example.ngrok.dev, which serves the application running on port 3000 of the host where you ran this command. If the webhook validation fails, ngrok immediately rejects the request in our global network. 

This blog post explains how this action works and how to add it to your traffic policy rules. 

Why apply Verify Webhook to your traffic policy?

This traffic policy action equips you to safely integrate webhooks into your applications without writing any verification code. It also allows you to develop and test webhooks without deploying applications to a public environment or configuring HTTP.  

But that’s not all - you can do even more with our flexible and expressive traffic policy. You can combine the Verify Webhook action with other traffic policy actions. Additionally, you can use CEL variables to craft powerful traffic policy rules customized to your needs. Unlike modules, traffic policies enable you to use a single configuration across all ngrok platforms—including the agent (CLI), API, Kubernetes Operator, and SDKs—ensuring consistency.

Implement the Verify Webhook traffic policy action

Add the Verify Webhook traffic policy action to the on_http_request phase of an HTTP endpoint. Let me show you how to configure the same Zoom webhook validation for a cloud endpoint

on_http_request:
  - actions:
      - type: verify-webhook
        config:
          provider: "zoom"
          secret: "ngrokrocks"
  - actions:
    - type: forward-internal
      config:
        url: https://api.internal
        binding: internal

This example traffic policy rule validates Zoom webhooks and forwards authorized requests to an internal endpoint at https://api.internal when verification succeeds. You can use this traffic policy rule with the dashboard, agent CLI, API, or SDKs. 

To apply this traffic policy to a cloud endpoint using the ngrok agent API client, run the following command, substituting the appropriate value for {YOUR_API_KEY} and {YOUR_DOMAIN}: 

ngrok api endpoints create \
     --api-key {YOUR_API_KEY} \
     --bindings public \
     --description "Cloud endpoint for webhooks" \
     --metadata “zoom webhook automation” \
     --url https://{YOUR_DOMAIN}
     --traffic-policy "$(cat policies.yaml)"

Configure the Verify Webhook action

You can configure this action using the configuration object  that includes the following properties:

  • provider - The name of a supported provider.
  • secret - The secret key used to validate requests from the provider.
  • enforce - Whether or not to block unverified webhook requests. ngrok will reject unverified webhook requests immediately if this is set to true (default). If this is false, you can still return an unsuccessful return code, but you have an opportunity to take other actions, such as sending a custom response. You can check whether the verification was successful through this action result variable and optionally take an action. This value defaults to true.

Evaluate traffic policy results

When the Verify Webhook traffic policy action executes, it returns an action.ngrok.verify_webhook object containing the following properties which can be used in subsequent traffic policy rules:

  • error_code - The code representing the error encountered when verifying this webhook request.
  • error_message - The corresponding error message specifying the issue encountered when verifying this webhook request.
  • verified - Whether or not the webhook request was verified.
  • secret - The secret used for this verification. 

Analyze logged events

The Verify Webhook traffic policy action logs an action_executed object containing the following properties to the event log:

  • expression_matched - The expressions upon which this action was invoked.
  • type - The action type.
  • config - The action config object for this invocation, as described above.
  • result - The action.ngrok.verify_webhook result object for this invocation, as described above. The secret value will be redacted in the event log. 

Chain traffic policy rules

You can combine traffic policy rules, use CEL variables within them, and conditionally apply rules based on the results of previously executed rules. The traffic policy rule below verifies webhook requests from Zoom and provides a different custom response depending on whether the validation succeeds. 

This rule sets enforce: false, meaning unauthorized requests will be allowed through—not to your upstream service, but to the next rule in your traffic policies. 

If you set this property to true, ngrok will reject the request when it reaches our global network and return the default error page and a 403 return code. Setting this property to false allows the traffic policy engine to execute the next rule in the configuration. 

The following rule—“debug unverified webhook request”—returns a custom response based on the value of the verified property of the actions.ngrok.verify_webhook object returned by the verify-webhook action. 

If the verified property is false, this rule returns a 407 code rather than the default of 403 and returns a custom error page. In this case, ngrok still blocks this request from reaching your upstream service, but you have more control over the response. 

If the verified property is true, this rule returns a 200 code and a custom response indicating that verification was successful. This rule demonstrates the power of conditional logic in your traffic policies. 

on_http_request:
  - name: zoom webhook
    actions:
      - type: verify-webhook
        config:
          provider: zoom
          secret: ngrokrocks
          enforce: false
  - name: debug unverified webhook request
    expressions:
      - actions.ngrok.verify_webhook.verified == false
    actions:
      - type: custom-response
        config:
          status_code: 407
          content: "<html><body><h1>Verification failed</h1><p>Service Unavailable.</p></body></html>"
          headers:
            content-type: text/html
            message: zoom verification failed!
            endpoint_id: "${endpoint.id}"
            error: "${actions.ngrok.verify_webhook.error.message}"
            failed_at: "${time.now}"
  - name: successful verification resp
    actions:
      - type: custom-response
        config:
          statusCode: 200
          headers:
            content-type: text/plain
          content: Verification successful!

How does it work?

The Verify Webhook traffic policy action authenticates webhook requests by validating the signature and timestamp of each request and performing an initial endpoint validation when required.  

Signature validation

This action validates incoming webhook signatures against a known secret to ensure authenticity. Then, depending on the verification result and your configuration, it either forwards the request to your upstream service if it’s valid or rejects it with response. You can specify whether to block unauthorized webhook requests, which is true by default.   

Endpoint verification

Some webhook providers require endpoint verification from your application before sending webhook requests. Endpoint verification helps providers prevent their webhook infrastructure from being used for DDoS attacks. When you configure webhook verification for the following providers, ngrok will automatically handle the endpoint verification request for your application.

  • Twitter
  • Wordline
  • Xero
  • Zoom

Prevent replay attacks

Validating the signature of incoming webhooks and performing endpoint verification up front are significant first steps; however, bad actors may still intercept properly signed webhook requests and replay them in rapid succession, causing a replay attack. To prevent this, some webhook providers include a mechanism to prevent these replay attacks by providing a signed timestamp in the webhook. ngrok will reject the webhook request if the difference between the current time and the included timestamp is outside the window of tolerance to prevent bad actors from replaying old requests in rapid succession. ngrok uses the webhook provider’s suggested tolerance value when it is available. Otherwise, ngrok will refuse requests older than 180 seconds.

Encrypted secrets

When you submit your traffic policy rules, you’ll provide a shared secret for validating webhook requests. ngrok encrypts your secret until it is needed to validate requests from your provider or when you request your traffic policy information through the API or dashboard. Rest assured ngrok will redact this value in log messages. 

Applying the Verify Webhook action in your traffic policy rules ensures signature verification, timestamp validation, secret validation, and replay attack prevention. 

What else can I do with webhook requests?

In addition to providing robust webhook validation, ngrok enables you to inspect, replay, and evaluate logged webhook requests, and migrating from our webhook verification module to the new Verify Webhook traffic policy action is a breeze!

Inspect webhook requests

ngrok’s Traffic Inspector lets you view your webhook requests and responses via the dashboard. Full capture mode enables you to store up to 10KB of request and response data, including parameters and headers. You can inspect the body and headers, view the raw request data in full capture mode, and replay the request. For a POST request, you’ll also see the body. This request demonstrates the traffic policy rules introduced above. You can see code and the custom response as specified in the traffic policy rules. 

Replay webhook requests

In addition to viewing your webhook requests, our Traffic Inspector allows you to replay your requests, enabling you to test and debug without performing the steps that trigger the webhook. For example, a push event on the GitHub repo triggered this webhook. You could replay it to test your app or service’s ability to handle the webhook without continuously pushing to the GitHub repository. 

Evaluate logged webhook verification events

When the Verify Webhook traffic policy action executes, it logs an action_executed event, as described above. You can analyze logged events to help understand your webhook traffic and debug failed events. 

Migrate existing webhook verification module configuration to a traffic policy rule

We recommend migrating your webhook verification module to a traffic policy action to take advantage of the flexibility and power of traffic policies. If you’re currently using our webhook verification module, it’s easy to migrate to the new Verify Webhook traffic policy action.

Say you have configured the following webhook verification module from GitHub on an Edge:

You can migrate this functionality to the new Verify Webhook traffic policy action by disabling the module on the Edge and adding the following configuration to your traffic policy rules via the agent CLI, agent config, SDKs, or Kubernetes Operator

on_http_request:
  - actions:
      - type: verify-webhook
        config:
          provider: "github"
          secret: "ngrokrocks"

Check it out, and learn more about traffic policies with ngrok

Add the Verify Webhook traffic policy action to your traffic policy rules, and let us know what you think. You can sign up for a free account to get started. Here are some other resources to help you learn more about using ngrok’s Traffic Policy engine:

Have questions or want to request a new feature? We’d love to hear from you. Hit us up at support@ngrok.com or create an issue or discussion on the ngrok community repo.

Share this post
Mandy Hubbard
Mandy Hubbard is a Sr. Technical Marketing Engineer. She is passionate about software quality, CI/CD, good processes, QA, and great documentation.
Product updates
Secure tunnels
News
Traffic Policy
Features
Webhooks
Development
Production