fix: add HS256 fallback for JWT verification in local dev
All checks were successful
CI / backend-tests (pull_request) Successful in 29s
CI / frontend-tests (pull_request) Successful in 29s

Local GoTrue signs JWTs with HS256, but the JWKS endpoint returns an
empty key set since there are no RSA keys. Fall back to HS256 shared
secret verification when JWKS fails, using SUPABASE_JWT_SECRET.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-22 09:38:52 +01:00
parent 0ec1beac8f
commit af55cdd8a6
7 changed files with 40 additions and 18 deletions

View File

@@ -44,26 +44,36 @@ def _extract_token(request: Request) -> str | None:
return parts[1]
def _verify_jwt(token: str) -> dict | None:
"""Verify JWT using JWKS public key. Returns payload or None."""
client = _get_jwks_client()
if not client:
def _verify_jwt_hs256(token: str) -> dict | None:
"""Verify JWT using HS256 shared secret. Returns payload or None."""
if not settings.supabase_jwt_secret:
return None
try:
signing_key = client.get_signing_key_from_jwt(token)
payload = jwt.decode(
return jwt.decode(
token,
signing_key.key,
algorithms=["RS256"],
settings.supabase_jwt_secret,
algorithms=["HS256"],
audience="authenticated",
)
return payload
except jwt.ExpiredSignatureError:
return None
except jwt.InvalidTokenError:
return None
except PyJWKClientError:
return None
def _verify_jwt(token: str) -> dict | None:
"""Verify JWT using JWKS (RS256), falling back to HS256 shared secret."""
client = _get_jwks_client()
if client:
try:
signing_key = client.get_signing_key_from_jwt(token)
return jwt.decode(
token,
signing_key.key,
algorithms=["RS256"],
audience="authenticated",
)
except jwt.InvalidTokenError, PyJWKClientError:
pass
return _verify_jwt_hs256(token)
def get_current_user(request: Request) -> AuthUser | None: