{"record":{"id":"dbbbba47618aaf71","repo":"PrefectHQ/fastmcp","slug":"unsupported-algorithm-v-r-for-identity-assertion","errorCode":null,"errorMessage":"Unsupported algorithm {v!r} for identity assertion: trusted issuers are verified via JWKS, so algorithm must be one of {supported}","messagePattern":"Unsupported algorithm (.+?) for identity assertion: trusted issuers are verified via JWKS, so algorithm must be one of (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/server/auth/identity_assertion.py","lineNumber":162,"sourceCode":"    def _validate_trusted_issuers(cls, v: list[str]) -> list[str]:\n        if not v:\n            raise ValueError(\"identity_assertion.trusted_issuers must not be empty\")\n        for issuer in v:\n            if not issuer or not issuer.strip():\n                raise ValueError(\"trusted_issuers entries must be non-empty strings\")\n        return v\n\n    @field_validator(\"algorithm\")\n    @classmethod\n    def _validate_algorithm(cls, v: str | None) -> str | None:\n        # Trusted issuers are verified via JWKS (public keys only), so the\n        # algorithm must be one of the asymmetric JWS algorithms JWTVerifier\n        # actually supports — HS* (shared-secret) has no JWKS equivalent, and\n        # anything else (EdDSA, or a typo like RS999) would otherwise surface\n        # as a 500 on the first exchange instead of a clean config error now.\n        if v is not None and v not in SUPPORTED_ASSERTION_ALGORITHMS:\n            supported = \", \".join(sorted(SUPPORTED_ASSERTION_ALGORITHMS))\n            raise ValueError(\n                f\"Unsupported algorithm {v!r} for identity assertion: trusted \"\n                f\"issuers are verified via JWKS, so algorithm must be one of \"\n                f\"{supported}\"\n            )\n        return v\n\n    @field_validator(\"algorithms\")\n    @classmethod\n    def _validate_algorithms(cls, v: dict[str, str] | None) -> dict[str, str] | None:\n        if v is not None:\n            for issuer, algorithm in v.items():\n                if algorithm not in SUPPORTED_ASSERTION_ALGORITHMS:\n                    supported = \", \".join(sorted(SUPPORTED_ASSERTION_ALGORITHMS))\n                    raise ValueError(\n                        f\"Unsupported algorithm {algorithm!r} for issuer \"\n                        f\"{issuer!r}: must be one of {supported}\"\n                    )\n        return v","sourceCodeStart":144,"sourceCodeEnd":180,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/server/auth/identity_assertion.py#L144-L180","documentation":"The optional global `algorithm` for identity assertion must be one of the asymmetric JWS algorithms that JWTVerifier supports (via JWKS). HS* symmetric algorithms and unknown names are rejected at config time so they fail as a clean configuration error instead of a 500 on the first token exchange.","triggerScenarios":"Setting `algorithm=\"HS256\"` (shared-secret — no JWKS equivalent), `algorithm=\"EdDSA\"` (unsupported here), or a typo like `algorithm=\"RS999\"` triggers `_validate_algorithm` during model validation.","commonSituations":"Copy-pasting a symmetric algorithm from a client-secret JWT setup; typos in algorithm names; migrating config from a shared-secret verifier to JWKS-based trusted-issuer verification without changing the algorithm.","solutions":["Set `algorithm` to a supported asymmetric algorithm (e.g. \"RS256\", \"ES256\") — see the sorted list in the error message","Remove the `algorithm` setting to use the default behavior (algorithms derived per issuer)","If you need HS*, that algorithm is not supported for JWKS-verified trusted issuers — switch the issuer to asymmetric keys"],"exampleFix":"# before\nIdentityAssertionSettings(trusted_issuers=[...], algorithm=\"HS256\")\n# after\nIdentityAssertionSettings(trusted_issuers=[...], algorithm=\"RS256\")","handlingStrategy":"validation","validationCode":"SUPPORTED = {\"RS256\", \"RS384\", \"RS512\", \"ES256\", \"ES384\", \"ES512\", \"PS256\", \"PS384\", \"PS512\"}\nif algorithm is not None and algorithm not in SUPPORTED:\n    raise ValueError(f\"algorithm {algorithm!r} unsupported for JWKS verification\")","typeGuard":"def is_supported_algorithm(alg: str | None) -> bool:\n    return alg is None or alg in SUPPORTED_ASSERTION_ALGORITHMS","tryCatchPattern":"try:\n    settings = IdentityAssertionSettings(algorithm=alg)\nexcept ValidationError as e:\n    logger.error(\"Invalid identity assertion algorithm %r: %s\", alg, e)\n    raise SystemExit(1)","preventionTips":["Only use asymmetric algorithms (RS*/ES*/PS*) with JWKS-based verification","Avoid copy-pasting HS* settings from shared-secret JWT configurations","Import SUPPORTED_ASSERTION_ALGORITHMS from the library instead of hardcoding names","Validate algorithm names at config load, not at first request"],"tags":["config","jwt","algorithm","validation"],"backgroundTag":"unsupported-jwt-algorithm","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}