Files
nuzlocke-tracker/.beans/nuzlocke-tracker-t9aj--migrate-jwt-verification-from-hs256-shared-secret.md
2026-03-22 09:23:12 +01:00

2.6 KiB

# nuzlocke-tracker-t9aj title: Migrate JWT verification from HS256 shared secret to asymmetric keys (JWKS) <<<<<<< Updated upstream status: todo type: task priority: low created_at: 2026-03-21T11:14:29Z updated_at: 2026-03-21T13:01:46Z

The backend currently verifies Supabase JWTs using an HS256 shared secret (SUPABASE_JWT_SECRET). Supabase recommends migrating to asymmetric keys (RS256) for better security.\n\nInstead of storing a shared secret, the backend would fetch public keys from Supabase's JWKS endpoint (https://<project>.supabase.co/.well-known/jwks.json) and verify tokens against those.\n\n## Changes needed\n\n- [ ] Update backend/src/app/core/auth.py to fetch and cache JWKS public keys\n- [ ] Change jwt.decode from HS256 to RS256 with the fetched public key\n- [ ] Remove SUPABASE_JWT_SECRET from config, docker-compose, deploy workflow, and .env files\n- [ ] Update tests\n\n## References\n\n- https://supabase.com/docs/guides/auth/signing-keys\n- https://supabase.com/docs/guides/auth/jwts

status: completed type: task priority: low created_at: 2026-03-21T11:14:29Z updated_at: 2026-03-22T08:14:34Z

The backend currently verifies Supabase JWTs using an HS256 shared secret (SUPABASE_JWT_SECRET). Supabase recommends migrating to asymmetric keys (RS256) for better security.\n\nInstead of storing a shared secret, the backend would fetch public keys from Supabase's JWKS endpoint (https://<project>.supabase.co/.well-known/jwks.json) and verify tokens against those.\n\n## Changes needed\n\n- [x] Update backend/src/app/core/auth.py to fetch and cache JWKS public keys\n- [x] Change jwt.decode from HS256 to RS256 with the fetched public key\n- [x] Remove SUPABASE_JWT_SECRET from config, docker-compose, deploy workflow, and .env files\n- [x] Update tests\n\n## References\n\n- https://supabase.com/docs/guides/auth/signing-keys\n- https://supabase.com/docs/guides/auth/jwts

Summary of Changes

Migrated JWT verification from HS256 shared secret to RS256 asymmetric key verification using JWKS:

  • auth.py: Added PyJWKClient that fetches and caches public keys from Supabase's JWKS endpoint (SUPABASE_URL/.well-known/jwks.json). Keys are cached for 1 hour.
  • config.py: Removed supabase_jwt_secret setting
  • pyproject.toml: Changed PyJWT to PyJWT[crypto] for RS256 support
  • docker-compose.yml: Configured local GoTrue for RS256 with mounted dev key
  • docker-compose.prod.yml: Replaced SUPABASE_JWT_SECRET with SUPABASE_URL
  • deploy.yml: Updated to pass SUPABASE_URL instead of SUPABASE_JWT_SECRET
  • tests: Updated to use mocked JWKS client with RSA key pairs

Stashed changes