PrefectHQ/fastmcp · error · TokenError

unsupported_grant_type

unsupported_grant_type

Error message

unsupported_grant_type: The JWT bearer grant is not supported by this authorization server

What it means

Raised by exchange_identity_assertion when a client presents a JWT bearer grant (ID-JAG, RFC 7523-style identity assertion) but the proxy has no IdentityAssertion provider and validator configured. Identity assertion is an opt-in capability; without configuration the server must reject the grant type per spec with 'unsupported_grant_type'.

Source

Thrown at fastmcp_slim/fastmcp/server/auth/oauth_proxy/proxy.py:1530

        client: OAuthClientInformationFull,
        params: IdentityAssertionParams,
    ) -> OAuthToken:
        """Exchange a SEP-990 ID-JAG for a short-lived FastMCP access token.

        Validates the ID-JAG against the configured trusted issuers (signature,
        `iss`, `aud`, `exp`, `typ`, `sub`, and `jti` replay), then mints a
        self-contained FastMCP access token carrying the asserted subject. No
        refresh token is issued — the client re-exchanges a fresh assertion.

        Raises:
            TokenError: ``invalid_grant`` if the assertion is rejected, or
                ``unsupported_grant_type`` if identity assertion is not configured.
        """
        if (
            self._identity_assertion is None
            or self._identity_assertion_validator is None
        ):
            raise TokenError(
                "unsupported_grant_type",
                "The JWT bearer grant is not supported by this authorization server",
            )

        # RFC 8707: when the request names a resource, it must be this server —
        # the same invariant (and the same skip-when-unconfigured behavior)
        # authorize() enforces for authorization requests.
        if params.resource and self._resource_url:
            server_url = str(self._resource_url)
            client_url = str(params.resource)
            if server_url_has_query(server_url):
                # Server has query params - require exact match for security
                resource_matches = client_url.rstrip("/") == server_url.rstrip("/")
            else:
                resource_matches = normalize_resource_url(
                    client_url
                ) == normalize_resource_url(server_url)
            if not resource_matches:

View on GitHub (pinned to 1f02114297)

Solutions

  1. Either stop sending the JWT bearer grant and use the standard authorization_code flow.
  2. Or configure the proxy with an identity assertion provider and validator so the grant type is supported.
  3. Verify you are pointing the client at the correct server deployment (one with ID-JAG enabled).
  4. Check the server's FastMCP version/config to confirm identity assertion support is enabled.

Example fix

# before: plain proxy, client sends jwt-bearer grant
proxy = OAuthProxy(upstream_authorization_endpoint=..., token_endpoint=...)
# after: enable identity assertion support
proxy = OAuthProxy(
    ...,
    identity_assertion=my_assertion_provider,
    identity_assertion_validator=my_validator,
)
Defensive patterns

Strategy: fallback

Validate before calling

// check server capability before attempting jwt-bearer grant
const supportsIdJag = serverConfig.identityAssertion !== undefined;
if (!supportsIdJag) useAuthorizationCodeFlow();

Try / catch

try {
  await idJagExchange(assertion);
} catch (e) {
  if (e.code === "unsupported_grant_type") {
    await authorizationCodeFlow(); // fallback
  } else throw e;
}

Prevention

When it happens

Trigger: POST /token with grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer (handled via _maybe_handle_id_jag) against an OAuthProxy instance constructed without identity_assertion/validator arguments.

Common situations: Client assumes the server supports ID-JAG but the server was never configured for it; version mismatch where the client was built against an ID-JAG-enabled deployment and points at a plain proxy; copy-pasted client config enabling jwt-bearer grants unconditionally.

Related errors


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