Security model
What the token guards, why the delivery side is open, and the optional per-webhook key.
beam has two surfaces with different threat models: claiming a name (the listen side) and delivering to it (the send side). They're secured differently on purpose.
The token guards the listen side
Claiming a name and receiving its traffic over the WebSocket requires a valid
Authorization: Bearer <token>. Without it, the upgrade is rejected 401. The
Worker compares the token constant-time against an API_TOKEN secret,
before the upgrade reaches the Durable Object — so auth failures never touch
durable state, and the name itself is the only public surface.
The delivery side is open by default
External providers must be able to POST without auth — they can't present your
token. So the unguessable name is the capability: whoever knows
/webhook/<name> can deliver to it.
If you need delivery authenticity, verify the provider's signature in your
local app. Because beam forwards all headers, GitHub's X-Hub-Signature-256,
Stripe's Stripe-Signature, and friends arrive intact and you verify them
exactly as you would in production.
Optional per-webhook key
When you control the URL the provider calls, you can lock the delivery side too.
Pass --key <secret> when you listen, and deliveries must arrive with a
matching ?key=<secret> (constant-time checked) or get 401:
beam webhook listen myhook --key s3cr3t
# → POST https://beam.example.com/webhook/myhook?key=s3cr3t ✅ 202
# → POST https://beam.example.com/webhook/myhook ❌ 401Two important properties:
- The key is stripped before forwarding — it never reaches your local app's logs.
- The key lives on the active listener's socket (it survives hibernation), so it's enforced for as long as you're connected.
key is config/env-driven too (BEAM_KEY / key= in the
config file).
Summary
| Surface | Default | Hardened with |
|---|---|---|
| Claim a name (listen) | Token-gated | API_TOKEN Worker secret, constant-time check |
| Deliver to a name | Open | --key per-webhook secret, or signature verify in your app |
| Payload integrity | TLS in transit | Provider signature verification (all headers forwarded) |