{"record":{"id":"705708ffaba7c87e","repo":"PrefectHQ/fastmcp","slug":"missing-client-assertion","errorCode":null,"errorMessage":"Missing client_assertion","messagePattern":"Missing client_assertion","errorType":"http","errorClass":"AuthenticationError","httpStatus":401,"severity":"error","filePath":"fastmcp_slim/fastmcp/server/auth/auth.py","lineNumber":282,"sourceCode":"            return await super().authenticate_request(request)\n\n        client = await self.provider.get_client(str(client_id))\n        if not client:\n            raise AuthenticationError(\"Invalid client_id\")\n\n        # Handle private_key_jwt authentication for CIMD clients\n        if client.token_endpoint_auth_method == \"private_key_jwt\":\n            # Validate assertion parameters\n            assertion_type = form_data.get(\"client_assertion_type\")\n            assertion = form_data.get(\"client_assertion\")\n\n            if assertion_type != JWT_BEARER_ASSERTION_TYPE:\n                raise AuthenticationError(\n                    f\"Invalid client_assertion_type: expected {JWT_BEARER_ASSERTION_TYPE}\"\n                )\n\n            if not assertion or not isinstance(assertion, str):\n                raise AuthenticationError(\"Missing client_assertion\")\n\n            # Validate the JWT assertion using CIMD manager\n            try:\n                await self._cimd_manager.validate_private_key_jwt(\n                    assertion=assertion,\n                    client=client,\n                    token_endpoint=self._token_endpoint_url,\n                )\n            except ValueError as e:\n                raise AuthenticationError(f\"Invalid client assertion: {e}\") from e\n\n            return client\n\n        # Delegate to SDK for other authentication methods\n        return await super().authenticate_request(request)\n\n\nclass AuthProvider(TokenVerifierProtocol):","sourceCodeStart":264,"sourceCodeEnd":300,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/server/auth/auth.py#L264-L300","documentation":"This AuthenticationError is raised during OAuth client authentication when a client registered with token_endpoint_auth_method='private_key_jwt' sends a token request with a valid client_assertion_type but an absent, empty, or non-string client_assertion form field. The server cannot verify the client's identity without the signed JWT assertion, so the request is rejected before JWT validation is attempted.","triggerScenarios":"POST to the token endpoint with a client_id whose CIMD document declares private_key_jwt, client_assertion_type set to urn:ietf:params:oauth:client-assertion-type:jwt-bearer, but the form field client_assertion is missing, empty, or not a string (e.g. a file part or repeated form value).","commonSituations":"Misconfigured OAuth client libraries that send assertion_type but forget the assertion; hand-rolled curl/token scripts missing the client_assertion parameter; form-encoding issues where the assertion arrives as a non-string part; template token-request code that never fills in the assertion.","solutions":["Set the client_assertion form field to a properly signed JWT (signed with the client's private key per its CIMD jwks).","Ensure the assertion is sent as a plain string form value, not as a file or repeated field.","Verify client_assertion_type is exactly urn:ietf:params:oauth:client-assertion-type:jwt-bearer and both fields travel together in the same form-encoded POST.","Regenerate or fix the client's token-request code so private_key_jwt clients always attach the assertion."],"exampleFix":"// before\ncurl -X POST /token -d 'client_id=https://client.example.com&grant_type=authorization_code&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer'\n// after\ncurl -X POST /token -d 'client_id=https://client.example.com&grant_type=authorization_code&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&client_assertion=<signed-jwt>'","handlingStrategy":"validation","validationCode":"form = token_request_form  # dict of form fields\nassert form.get('client_assertion_type') == 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer'\nassertion = form.get('client_assertion')\nif not isinstance(assertion, str) or not assertion:\n    raise ValueError('client_assertion form field must be a non-empty string JWT')","typeGuard":"def has_client_assertion(form: dict) -> bool:\n    a = form.get('client_assertion')\n    return isinstance(a, str) and len(a) > 0","tryCatchPattern":null,"preventionTips":["Always send client_assertion and client_assertion_type together in the token request form body.","Use a maintained OAuth client library that implements private_key_jwt instead of hand-rolling the form.","Log form keys (not values) on auth failure to spot missing fields quickly.","Send the assertion as a plain form field, never as a multipart file part."],"tags":["oauth","authentication","jwt","client-assertion"],"backgroundTag":"missing-oauth-client-assertion","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}