PrefectHQ/fastmcp · error · ValueError

Unsupported JWK key type: {key_type!r}

Error message

Unsupported JWK key type: {key_type!r}

What it means

A ValueError from _jwk_to_pem (fastmcp_slim/fastmcp/server/auth/cimd.py:48) when converting a JWK from a CIMD document's jwks into PEM for JWT signature verification and the key's 'kty' is neither 'RSA' nor 'EC'. Only RSA and EC asymmetric keys are supported; oct (symmetric) and OKP (Ed25519) keys are rejected.

Source

Thrown at fastmcp_slim/fastmcp/server/auth/cimd.py:54

    SSRFFetchError,
    ssrf_safe_fetch_response,
    validate_url,
)
from fastmcp.utilities.logging import get_logger

if TYPE_CHECKING:
    from fastmcp.server.auth.providers.jwt import JWTVerifier

logger = get_logger(__name__)


def _jwk_to_pem(key_data: dict[str, Any]) -> str:
    key_type = key_data.get("kty")
    if key_type == "RSA":
        return jwk.import_key(key_data, "RSA").as_pem().decode("utf-8")
    if key_type == "EC":
        return jwk.import_key(key_data, "EC").as_pem().decode("utf-8")
    raise ValueError(f"Unsupported JWK key type: {key_type!r}")


class CIMDDocument(BaseModel):
    """CIMD document per draft-parecki-oauth-client-id-metadata-document.

    The client metadata document is a JSON document containing OAuth client
    metadata. The client_id property MUST match the URL where this document
    is hosted.

    Key constraint: token_endpoint_auth_method MUST NOT use shared secrets
    (client_secret_post, client_secret_basic, client_secret_jwt).

    redirect_uris is required and must contain at least one entry.
    """

    client_id: AnyHttpUrl = Field(
        ...,
        description="Must match the URL where this document is hosted",

View on GitHub (pinned to 1f02114297)

Solutions

  1. Publish an RSA or EC key in the CIMD document's jwks (kty exactly 'RSA' or 'EC', uppercase).
  2. Replace OKP/Ed25519 keys with ES256 (EC P-256) or RS256 (RSA) signing keys in the client.
  3. Check every jwks entry for a present, correctly-cased kty value.
  4. If you control the client, generate a new supported key pair and update the hosted CIMD document.

Example fix

// before
{"kty": "OKP", "crv": "Ed25519", "x": "..."}
// after
{"kty": "EC", "crv": "P-256", "x": "...", "y": "..."}
Defensive patterns

Strategy: validation

Validate before calling

SUPPORTED_KTY = {'RSA', 'EC'}
keys = cimd_doc.get('jwks', {}).get('keys', [])
for k in keys:
    if k.get('kty') not in SUPPORTED_KTY:
        raise ValueError(f"CIMD jwks key kty={k.get('kty')!r} unsupported; publish RSA or EC")

Type guard

def is_supported_jwk(key: dict) -> bool:
    return key.get('kty') in ('RSA', 'EC')

Try / catch

try:
    client = await cimd_manager.get_client(client_id)
except ValueError as e:
    logger.error('CIMD key issue: %s', e)
    raise HTTPException(401, 'invalid_client') from e

Prevention

When it happens

Trigger: A CIMD document's jwks contains a key with kty='oct', kty='OKP', a missing kty field, or a misspelled value (e.g. lowercase 'rsa'); _extract_public_key_from_jwks selects that key while validating a private_key_jwt assertion.

Common situations: Clients publishing symmetric keys in their CIMD jwks (invalid for this flow); Ed25519 (OKP) signing keys not yet supported by this implementation; hand-written jwks JSON with a typo or a missing kty field.

Related errors


AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29). Data as JSON: /api/errors/ceff000d53514a4b. Report an issue: GitHub.