PrefectHQ/fastmcp · error · AuthenticationError

Invalid client_assertion_type: expected {JWT_BEARER_ASSERTIO

Error message

Invalid client_assertion_type: expected {JWT_BEARER_ASSERTION_TYPE}

What it means

When a client authenticates with token_endpoint_auth_method == 'private_key_jwt', the token request must carry client_assertion_type equal to the JWT-bearer IETF value (urn:ietf:params:oauth:client-assertion-type:jwt-bearer). If the form field is missing or has any other value, AuthenticationError('Invalid client_assertion_type: expected ...') is raised.

Source

Thrown at fastmcp_slim/fastmcp/server/auth/auth.py:277

        client_id = form_data.get("client_id")

        # If client_id is not in form data, delegate to SDK
        # This handles client_secret_basic which sends credentials in Authorization header
        if not client_id:
            return await super().authenticate_request(request)

        client = await self.provider.get_client(str(client_id))
        if not client:
            raise AuthenticationError("Invalid client_id")

        # Handle private_key_jwt authentication for CIMD clients
        if client.token_endpoint_auth_method == "private_key_jwt":
            # Validate assertion parameters
            assertion_type = form_data.get("client_assertion_type")
            assertion = form_data.get("client_assertion")

            if assertion_type != JWT_BEARER_ASSERTION_TYPE:
                raise AuthenticationError(
                    f"Invalid client_assertion_type: expected {JWT_BEARER_ASSERTION_TYPE}"
                )

            if not assertion or not isinstance(assertion, str):
                raise AuthenticationError("Missing client_assertion")

            # Validate the JWT assertion using CIMD manager
            try:
                await self._cimd_manager.validate_private_key_jwt(
                    assertion=assertion,
                    client=client,
                    token_endpoint=self._token_endpoint_url,
                )
            except ValueError as e:
                raise AuthenticationError(f"Invalid client assertion: {e}") from e

            return client

View on GitHub (pinned to 1f02114297)

Solutions

  1. Send `client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer` in the token request form body.
  2. Also include a signed `client_assertion` JWT (next check in the same flow) so the request passes subsequent validation.
  3. If the client shouldn't use private_key_jwt, register/configure it with the intended auth method (e.g. client_secret_post).
  4. Use a conformant OAuth client library instead of a hand-built token request.

Example fix

// before
requests.post(token_url, data={"client_id": cid, "client_assertion": jwt})

// after
requests.post(token_url, data={
    "client_id": cid,
    "client_assertion": jwt,
    "client_assertion_type": "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
})
Defensive patterns

Strategy: validation

Validate before calling

JWT_BEARER = 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer'
assert form['client_assertion_type'] == JWT_BEARER, 'invalid client_assertion_type'
assert isinstance(form.get('client_assertion'), str) and form['client_assertion']

Try / catch

# client side
if response.status_code == 401 and response.json().get('error') == 'invalid_client':
    logger.error('check client_assertion_type and client_assertion fields')

Prevention

When it happens

Trigger: Token request with client_id in form data for a private_key_jwt client where form_data['client_assertion_type'] is absent or not 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer' (auth.py:276-279).

Common situations: Custom OAuth clients hand-rolling the token request and omitting the assertion_type field; libraries sending client_secret_post-style bodies while the server expects private_key_jwt; misconfigured client registered as private_key_jwt but actually using another flow.

Related errors


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