Receive Auth0 Webhooks Locally (Test Auth0 Log Streams on localhost)

Test Auth0 webhooks locally by streaming Auth0 Log Streams to localhost. Inspect the real batch of log events, forward to your handler, and verify the token.

Receive Auth0 Webhooks Locally (Test Auth0 Log Streams on localhost)

You are wiring up an Auth0 integration — shipping login events to your own analytics, reacting to failed logins, or syncing user activity — and you need to see your handler react to a real batch of Auth0 log events. The problem is immediate: Auth0 delivers these events through a Log Stream that will only POST to a public URL, and your handler is running on localhost:8080. Auth0 has no way to reach it.

The usual workarounds are painful. Deploying to a staging server for every code change is slow. Pasting a sample event from the docs into curl gives you a guess at the real request, not the real headers and the real batched array Auth0 actually sends. What you want is to receive Auth0 webhooks locally — real log events, hitting your local handler, with a URL that does not change every time you restart.

This guide shows how to do exactly that.

Why receiving Auth0 webhooks locally is tricky

Auth0's main webhook mechanism is Log Streams. You create a Custom Webhook stream, and Auth0 batches your tenant's log events (logins, signups, token exchanges, failed logins, Management API calls) and POSTs them to a URL as JSON. The catch is the same as with any provider: Auth0 sits on the public internet; your dev machine usually does not. It is behind a router, a corporate firewall, or both, with no public IP and no inbound ports open.

So you need something in the middle: a public endpoint Auth0 can hit, that relays each request down to your laptop without you opening a single firewall port. That is what Webhook Relay does — and unlike a random tunnel URL, the endpoint is stable, so you configure the Auth0 stream once and never touch it again.

Step 1: Inspect the real payload with Webhook Bin

Before you write any handler code, find out what Auth0 actually sends. Open the free Webhook Bin — no signup — and you get an instant public URL.

  1. Copy the Webhook Bin URL.
  2. In the Auth0 Dashboard, go to Monitoring → Streams → Create Stream.
  3. Choose Custom Webhook, give it a name, and paste the URL into Payload URL.
  4. Set Content Type to application/json and Content Format to JSON Lines (or JSON Array), then save.

Now perform an action that produces a log event — sign in to your app, trigger a failed login, or call the Management API. Auth0 batches recent events and POSTs them to your endpoint. Inspect the captured request in Webhook Bin: the full JSON body (an array of log events, each with type, date, client_id, ip, and more), the content type, and every header — including the Authorization header if you set a token.

Now you know the exact shape of the data — and that it arrives as a batch, not one event at a time — before writing a line of code. For more on this approach, see How to test webhooks and What is a webhook.

Step 2: Forward the events to localhost with the relay agent

Once you know the payload, route those same events into your local handler. Sign up for Webhook Relay, install the relay agent (CLI or Docker), and create a bucket — say auth0. The bucket gives you a stable public input endpoint.

Start forwarding to your local server:

relay forward --bucket auth0 http://localhost:8080/api/logs

The agent opens an outbound connection to Webhook Relay and streams every incoming request down to http://localhost:8080/api/logs. Because the connection is outbound, there are no firewall ports to open and no public IP needed — this works from your laptop, behind a corporate proxy, or inside a Kubernetes cluster. Running in Docker? The same command works in the official webhookrelay/webhookrelayd image. Full details are in the localhost forwarding docs.

Now update the Log Stream's Payload URL to your Webhook Relay endpoint (or just create the stream there from the start). Trigger a login and watch the batch arrive on localhost.

Auth0-specific configuration and quirks

A few Auth0 details worth knowing:

  • Where to add it: Auth0 Dashboard → Monitoring → Streams → Create Stream → Custom Webhook. One Payload URL per stream, though you can reuse the same URL across multiple streams.
  • Batched delivery: Auth0 does not send one event per request. Each POST body is an array (or newline-delimited objects in JSON Lines format) containing multiple log events. Loop over them in your handler.
  • Content format: JSON Lines delivers one JSON object per line; JSON Array delivers a single array. Pick the one your parser handles and be consistent.
  • Single route: your handler only needs one endpoint (such as /api/logs) that accepts HTTP POST.
  • Actions, too: beyond Log Streams, an Auth0 Action can call out to a custom webhook with fetch() during a flow (for example, post to your endpoint on every login). Those requests also need a public URL, so the same relay setup applies.
  • Health view: check the stream's Health tab in the dashboard to confirm Auth0 is delivering and seeing 2xx responses from your endpoint.

Step 3: Verify the Auth0 webhook token

A custom webhook stream lets you set an optional Authorization Token. When you configure one, Auth0 sends it in the Authorization header (formatted as Bearer <token>) on every request. Your handler should compare the received header against the token you configured — in constant time — before trusting the payload. This is a shared-secret check rather than a per-request HMAC signature, so guard the token like a password and serve the endpoint over HTTPS.

If you are integrating with a provider that signs each request with an HMAC instead, you can sanity-check that flow by pasting a captured body, your secret, and the received signature into the free HMAC signature verifier. For language-specific code and the common pitfalls — reading the body after a JSON parser has consumed it, timing-safe comparison — read Verify a webhook signature.

Replay and iterate

This is where local development gets fast:

  • Replay from Webhook Relay — past requests are stored on your bucket, so you can resend a captured batch of log events without producing new activity in Auth0.
  • Iterate on your handler by editing code and replaying the same delivery until it parses the array, handles each event type, and checks the token correctly. No commits, no pushes, no deploys just to test a code path.
  • No flaky test logins — once you have one real batch captured, you can replay it endlessly instead of repeatedly logging in to generate events.

Because the Webhook Relay endpoint is stable, you can stop and restart the agent, reboot your machine, or come back next week — the Auth0 Log Stream configuration never needs to change.

Get started

  1. Inspect the real payload in the free Webhook Bin — no signup needed.
  2. Create a Webhook Relay account, install the agent, and run relay forward --bucket auth0 http://localhost:8080/api/logs.
  3. Point your Auth0 custom webhook stream at the stable endpoint, trigger a login, and watch the batch hit localhost.

You will be testing real Auth0 log events against your local handler in a few minutes — no deploys, no open firewall ports, and a URL you configure exactly once.