supabase edge function error: JWT signature does not match when calling external API
Fixes Supabase edge functions that fail with 'JWT signature does not match' by correcting the JWT secret the function validates against. Use when a Supabase edge function returns this exact signature error when verifying a token or calling an external API. Not for expired tokens, not for row-level-security denials, not for JWT errors outside Supabase.
TL;DR
Verify the token against the same JWT secret that signed it. Supabase edge functions check signatures with the project's JWT secret, so if the function uses the wrong secret, a rotated secret, or the anon key instead, every signature check fails. Align the secret and the error goes away.
supabase edge function error: JWT signature does not match when calling external APISteps
- Log the token's decoded header and payload (never log the full token) and note the issuer and key id claims. Expected: you can see which project and key the token claims to come from.
- In the Supabase dashboard, open the project settings and confirm the current JWT secret. Expected: you have the canonical secret the project signs tokens with.
- Compare: check which value your edge function reads for verification (its environment config). Expected: you find whether the function points at the right secret or something else, like the anon key or a stale copy.
- If the project secret was rotated or the function caches an old one, update the function's config to the current JWT secret and redeploy. Expected: the deployed function holds the current secret.
- Check the token itself is complete: not truncated in transit, no whitespace appended, and signed with HS256. Expected: the token parses cleanly as three dot-separated parts.
- Retry the edge function call. Expected: the signature verifies and the call proceeds past auth.
Use this when
- A Supabase edge function returns exactly "JWT signature does not match".
- The failure started right after a secret rotation or a redeploy.
- The same token verifies fine in one environment but not another.
Not for this skill when
- The token is expired (that is a different error, fix the expiry).
- The failure is a row-level-security policy denial, not a signature check.
- The JWT comes from a non-Supabase issuer with its own key setup.
Variant phrasings
- Supabase edge function JWT signature mismatch
- Supabase function JWT verification failed
- JWT signature does not match Supabase edge function
Why it happens
A JWT signature only verifies against the exact secret that signed it. Generated clients often wire the wrong value into the edge function: the public anon key instead of the JWT secret, a secret copied from the wrong project, or a stale copy left over after the dashboard secret was rotated. Any of those makes every signature check fail even though the token itself is fine.
Edge cases
- Rotating the JWT secret in the dashboard invalidates all outstanding tokens; expect a short window of failures while clients pick up new tokens.
- The anon key and the JWT secret are different values; swapping them is the most common wiring mistake.
- Tokens truncated by logging or URL handling fail signature checks even with the right secret, so check token integrity before blaming the secret.
Provenance
Resolved from the public thread: https://vectle.com/posts/pstq5OVHMRv8iZ1DS_tFMl6w