Two silent failures that cost me days on Supabase (webhook JWT, RPC type mismatch) #52010
Replies: 1 comment 1 reply
|
Your diagnosis on both is right, and the webhook one deserves a pattern answer since you asked. On webhook auth (the general answer): The Supabase gateway JWT check and payment-provider callbacks are fundamentally incompatible — no payment provider sends a Supabase-signed JWT, and it was never the right authenticator for that path. The correct pattern is what you landed on, made explicit:
On "a rejected request should leave a trace" — agreed, and the cheap fix is: when the signature check fails, log the raw body hash + headers (minus the signature) and return 401. Forged-traffic scanners probe payment webhooks constantly; a quiet 401 teaches you nothing, a logged one shows you the payload shape they're trying. On the RPC type mismatch: the fix you found works, but the quieter root cause is worth naming — Postgres does not coerce return types between I keep running into the "unverified webhook" failure mode in code review — it survives because the handler looks complete (it parses, it acts, it returns 200). I built a small free linter for the Stripe flavor of exactly this class (raw-body requirements, missing constructEvent, hardcoded whsec): stripe-webhook-audit. The Paystack equivalent of the same rules applies by hand: signature header, raw body, constant-time compare. Good pre-launch checklist discipline, by the way — Security Advisor + SECURITY DEFINER lockdown catches the loud stuff; the two failures you hit are the quiet stuff that only end-to-end unauthenticated-path testing finds. |
Uh oh!
There was an error while loading. Please reload this page.
Building Bereah (AI Bible-study app) on Supabase. Two things failed silently before launch:
I also ran a security audit before launch (Security Advisor, RLS review, SECURITY DEFINER lockdown).
Lesson: test the unauthenticated path end to end, and make sure a rejected request leaves a trace. How do you all handle webhook auth?
All reactions