diff --git a/src/fastmcp/server/auth/providers/jwt.py b/src/fastmcp/server/auth/providers/jwt.py index 5640fa390..6368df12c 100644 --- a/src/fastmcp/server/auth/providers/jwt.py +++ b/src/fastmcp/server/auth/providers/jwt.py @@ -225,6 +225,12 @@ class JWTVerifier(TokenVerifier): }: raise ValueError(f"Unsupported algorithm: {algorithm}.") + if jwks_uri and algorithm.startswith("HS"): + raise ValueError( + "HMAC algorithms (HS256/HS384/HS512) require a shared secret via " + "public_key and cannot be used with jwks_uri" + ) + # Parse scopes if provided as string parsed_required_scopes = ( parse_scopes(required_scopes) if required_scopes is not None else None diff --git a/tests/server/auth/providers/test_supabase.py b/tests/server/auth/providers/test_supabase.py index 5182ca5e5..5d1ce06f9 100644 --- a/tests/server/auth/providers/test_supabase.py +++ b/tests/server/auth/providers/test_supabase.py @@ -93,7 +93,7 @@ class TestSupabaseProvider: @pytest.mark.parametrize( "algorithm", - ["HS256", "RS256", "ES256"], + ["RS256", "ES256"], ) def test_algorithm_configuration(self, algorithm): """Test that algorithm can be configured for different JWT signing methods.""" @@ -106,6 +106,15 @@ class TestSupabaseProvider: assert isinstance(provider.token_verifier, JWTVerifier) assert provider.token_verifier.algorithm == algorithm + def test_algorithm_hs256_rejected(self): + """Test that HS256 is rejected with Supabase JWKS verification.""" + with pytest.raises(ValueError, match="cannot be used with jwks_uri"): + SupabaseProvider( + project_url="https://abc123.supabase.co", + base_url="https://myserver.com", + algorithm="HS256", + ) + def test_algorithm_default_es256(self): """Test that algorithm defaults to ES256 when not specified.""" provider = SupabaseProvider( diff --git a/tests/server/auth/test_jwt_provider.py b/tests/server/auth/test_jwt_provider.py index 19b0f9370..9512cc1dc 100644 --- a/tests/server/auth/test_jwt_provider.py +++ b/tests/server/auth/test_jwt_provider.py @@ -201,6 +201,15 @@ class TestSymmetricKeyJWT: assert provider.algorithm == "HS256" assert provider.jwks_uri is None + def test_initialization_rejects_hs_algorithm_with_jwks_uri(self): + """Test that HMAC algorithms cannot be used with JWKS URI.""" + with pytest.raises(ValueError, match="cannot be used with jwks_uri"): + JWTVerifier( + jwks_uri="https://test.example.com/.well-known/jwks.json", + issuer="https://test.example.com", + algorithm="HS256", + ) + def test_initialization_with_different_symmetric_algorithms( self, symmetric_key_helper: SymmetricKeyHelper ):