Stop pasting Polar webhook secrets into online signature debuggers
Checkout is green. The Polar delivery log shows a 2xx. Your app still thinks the customer is on the free tier.
You open an online “JWT / HMAC debugger,” paste the raw body, paste POLAR_WEBHOOK_SECRET, and hit Verify. Two problems just stacked: (1) the secret may now live in someone else’s server logs, and (2) you still have not proved the sandbox vs live mismatch that usually causes this class of bug.
Official Polar docs win when they disagree with anything here.
I already covered sandbox vs live webhooks and the Next.js / Vercel go-live env pass. This piece is narrower: how to practice webhook signature verification without leaking production secrets.
Why the online debugger habit hurts
A production webhook secret is a credential. Paste it into a SaaS playground and you have:
- Given a third party the ability to forge deliveries that look signed
- Often mixed sandbox and live secrets in the same paste session
- Trained yourself to debug entitlements in a tool that never sees your Route Handler, raw body buffering, or idempotency store
Signature success in a playground does not mean your Next.js handler verified the same bytes Polar sent. Many frameworks re-parse JSON and destroy the exact body Polar signed.
Minimal safe practice loop
- In Polar (sandbox first), open a recent delivery and copy headers + raw body locally into a file you will not commit.
- Verify offline on your laptop (Node script,
openssl, or a local HTML tool that never uploads). - Only after sandbox is green, repeat with the live endpoint and the live secret — never reuse the sandbox secret “just to see.”
- Confirm your handler uses the raw request body (not
JSON.stringify(await req.json())). - Grant entitlements idempotently once per
(environment, customer/subscription)— not once per order id alone if retries exist.
If you cannot do step 1 without opening a public website, stop. The secret stays on your machine.
Two schemes, two endpoints
During Polar’s dual-mode periods, sandbox and live can look alike until they do not: different hosts, different products, different secrets, sometimes different signing schemes. Keep:
| World | Dashboard | Token / secret | Webhook URL |
|---|---|---|---|
| Sandbox | sandbox.polar.sh | sandbox-only | stable tunnel or dedicated sandbox host |
| Live | polar.sh | live-only | custom domain (not a PR preview URL) |
Never register the production webhook against a changing *.vercel.app preview hostname.
Soft sell (kit)
If you want a packaged offline dual-mode lab (fixtures, verify/sign drills, Next.js stub, idempotency notes) without wiring your real store first:
Dual-Mode Webhook Lab ($14):
https://buy.polar.sh/polar_cl_6k1TwXMqdt8hiPyOxPrAZCLbKIfYmkeBzUUXw1QggrO
Product page: https://gumbosveins.github.io/dual-mode-webhook-lab/
Companion go-live pack:
Next.js / Vercel Production Launch Kit ($19):
https://buy.polar.sh/polar_cl_uxzixqNM81nkPoIW3um9aacYzAmA1bXQbWqUe3EQE75
Buy only if it saves you a night. The free loop above is enough for a solo app.
More in this series
- The Next.js / Vercel production env mistakes that break launches
- Polar sandbox vs live webhooks — why checkout works and entitlements do not
- Build a Vercel env matrix offline before you merge
Educational material only. Vendor names belong to their owners.
Top comments (0)