name: supabase-gotrue-jwt-secret-mismatch
description: Diagnóstico e correção de GoTrue self-hosted rejectando JWT com "invalid signature" — token de serviço com chave secreta desatualizada
triggers:
- GoTrue 401 invalid JWT signature
- SERVICE_ROLE_KEY JWT verification failing
- JWT secret mismatch in self-hosted Supabase
Supabase Self-Hosted: JWT Secret Mismatch no GoTrue
Sintoma
Edge functions (ou chamadas diretas) usando SERVICE_ROLE_KEY para admin via /auth/v1/admin/* retornam:
`
{"msg":"invalid JWT: unable to parse or verify signature, signature is invalid"}
`
Mas o mesmo token funciona para PostgREST (REST API).
Diagnóstico
1. Identificar a JWT_SECRET atual do container GoTrue
`bash
sshpass -p '
"docker exec deploy-vps-auth-1 env | grep -E 'JWT_SECRET|GOTRUE_JWT_SECRET'"
`
2. Gerar token de teste com a chave atual
`python
python3 << 'EOF'
import jwt, time
secret = '
payload = {
'iss': 'supabase', 'ref': 'rochasales',
'role': 'supabase_admin',
'iat': int(time.time()),
'exp': int(time.time()) + 28800,
'is_super_admin': True,
'email': 'service_role@rochasales'
}
print(jwt.encode(payload, secret, algorithm='HS256'))
EOF
`
3. Testar diretamente no GoTrue (bypass Kong)
`bash
docker exec deploy-vps-auth-1 wget -O- -q 'http://127.0.0.1:9999/admin/users' \
--header="Authorization: Bearer
--header="apikey:
`
Se o novo token funciona → o SERVICE_ROLE_KEY no container está desatualizado (gerado com chave secreta antiga).
Solução
Opção A: Atualizar o SERVICE_ROLE_KEY no container (substituição direta)
`bash
Gerar o novo token (veja passo 2 acima)
NOVO_TOKEN="
Verificar nome da variável no container
sshpass -p '
"docker exec deploy-vps-auth-1 env | grep SERVICE_ROLE_KEY"
Anotar o nome exato da variável (ex: SUPABASE_SERVICE_ROLE_KEY)
Aplicar temporariamente (sobrevive reinício do container mas não do docker compose)
sshpass -p '
"docker exec deploy-vps-auth-1 env set SERVICE_ROLE_KEY=$NOVO_TOKEN"
`
Opção B: Atualizar via docker-compose secrets (permanente)
`bash
No diretório com docker-compose.yml do Supabase:
echo "
docker-compose up -d auth
`
Opção C: Atualizar .env se tiver acesso
Se a .env do docker-compose contém GOTRUE_JWT_SECRET, atualize também SERVICE_ROLE_KEY com o novo token gerado na mesma secret.
Por que acontece
Quando o Supabase self-hosted é migrado ou recriado (reinstall, backup restore), o JWT_SECRET pode ser regenerado. O SERVICE_ROLE_KEY é um JWT fixo salvo em config/secrets — não se atualiza automaticamente. Resultado: tokens emitidos pelo serviço têm assinaturas incompatíveis com a nova chave.
Verificação pós-correção
`bash
Testar listar usuários (bypass Kong direto ao GoTrue)
docker exec deploy-vps-auth-1 wget -O- -q 'http://127.0.0.1:9999/admin/users' \
--header="Authorization: Bearer
--header="apikey:
Esperado: JSON com array de usuários, status 200
`
Armadilhas
- - Kong também rejeita tokens inválidos na rota
/auth/v1/*→ testar direto no GoTrue comdocker execpara confirmar se o problema é Kong ou GoTrue - -
VERIFY_JWT=falseno GoTrue não desabilita verificação para admin endpoints com Bearer token — admin endpoints SEMPRE validam assinatura - - Edge functions (Deno) usam
JWT_SECRETdiferente doSERVICE_ROLE_KEY— se a função gera tokens localmente, precisa usar o mesmo secret que o GoTrue