name: supabase-edge-function-401-debug
description: Debug 401 Unauthorized errors in Supabase Edge Functions when JWT verification fails despite valid tokens
category: devops
Supabase Edge Function 401 Unauthorized Debug
Problem
Edge Function /functions/v1/manage-users always returns {"error":"Unauthorized"} even with valid JWT tokens. The signature verification fails silently.
Root Cause
Trailing newline (\n) in GOTRUE_JWT_SECRET environment variable in the auth container. The auth signs tokens with secret+\n, but the functions container's JWT_SECRET (without \n) tries to verify with the raw secret. Signatures never match.
Discovery Method
When JWT_SECRET appears byte-identical via hex dump but tokens still fail verification, check for trailing newlines:
`bash
docker exec
docker exec
If auth has +1 byte, there's a trailing \n
`
Architecture on VPS
`
Kong → nginx (functions-proxy:9000) → Deno runtime (functions-1:9000)
`
The nginx just proxy-passes, no auth filtering there.
Key Discovery Steps
1. JWT token valid via Python verification → problem is on the verification side
2. Kong in DB-less mode, no auth plugins
3. Kong routes to functions-proxy (nginx), which proxies to functions-1 (Deno)
4. Deno runtime uses --main-service /home/deno/functions/main but /manage-users also works
5. Edge Function code in container at /home/deno/functions/manage-users/index.ts
6. docker logs often shows no application logs (only shutdown signals)
7. Python hmac.new() with base64url encoding can verify signatures independently
Solution
Remove the trailing \n from GOTRUE_JWT_SECRET in the auth container's environment or add it to JWT_SECRET in the functions container to match.
Prevention
When setting JWT_SECRET in docker-compose or environment files, ensure no trailing newlines. Use echo -n when setting env vars in shell scripts.