PrefectHQ/fastmcp · error · AuthorizeError

invalid_request

invalid_request

Error message

invalid_request: Invalid redirect_uri.

What it means

Inside authorize, redirect_uri validation is wrapped in a try/except; if any exception occurs while validating that the requested redirect_uri is acceptable for the client, the provider raises AuthorizeError('invalid_request', 'Invalid redirect_uri.'). In the current implementation the check body largely passes validation through to the AuthorizationHandler, so this fires when validation raises unexpectedly.

Source

Thrown at fastmcp_slim/fastmcp/server/auth/providers/in_memory.py:121

        """
        if client.client_id not in self.clients:
            raise AuthorizeError(
                error="unauthorized_client",
                error_description=f"Client '{client.client_id}' not registered.",
            )

        # Validate redirect_uri (already validated by AuthorizationHandler, but good practice)
        try:
            # OAuthClientInformationFull should have a method like validate_redirect_uri
            # For this test provider, we assume it's valid if it matches one in client_info
            # The AuthorizationHandler already does robust validation using client.validate_redirect_uri
            if client.redirect_uris and params.redirect_uri not in client.redirect_uris:
                # This check might be too simplistic if redirect_uris can be patterns
                # or if params.redirect_uri is None and client has a default.
                # However, the AuthorizationHandler handles the primary validation.
                pass  # Let's assume AuthorizationHandler did its job.
        except Exception as e:  # Replace with specific validation error if client.validate_redirect_uri existed
            raise AuthorizeError(
                error="invalid_request", error_description="Invalid redirect_uri."
            ) from e

        auth_code_value = f"test_auth_code_{secrets.token_hex(16)}"
        expires_at = time.time() + DEFAULT_AUTH_CODE_EXPIRY_SECONDS

        # Ensure scopes are a list
        scopes_list = params.scopes if params.scopes is not None else []
        if client.scope:  # Filter params.scopes against client's registered scopes
            client_allowed_scopes = set(client.scope.split())
            scopes_list = [s for s in scopes_list if s in client_allowed_scopes]

        if client.client_id is None:
            raise AuthorizeError(
                error="invalid_client", error_description="Client ID is required"
            )
        auth_code = AuthorizationCode(
            code=auth_code_value,

View on GitHub (pinned to 1f02114297)

Solutions

  1. Ensure params.redirect_uri exactly matches one of the URIs in the client's registered redirect_uris (scheme, host, port, path)
  2. Check the exception chained via `from e` in logs to see the underlying validation failure
  3. Register the desired redirect URI via register_client before authorizing

Example fix

// before
params = AuthorizationParams(redirect_uri=None, ...)  # client requires exact URIs
provider.authorize(client, params)
// after
params = AuthorizationParams(redirect_uri="http://localhost:8080/callback", ...)
provider.authorize(client, params)
Defensive patterns

Strategy: validation

Validate before calling

redirect_uri = "http://localhost:8080/callback"
assert redirect_uri in (client.redirect_uris or []), f"redirect_uri {redirect_uri} not registered"
params = AuthorizationParams(redirect_uri=redirect_uri, ...)

Type guard

def redirect_allowed(client, redirect_uri: str | None) -> bool:
    return redirect_uri is not None and redirect_uri in (client.redirect_uris or [])

Try / catch

try:
    redirect = provider.authorize(client, params)
except AuthorizeError as e:
    if e.error == "invalid_request":
        logger.error("redirect_uri %r rejected: %s", params.redirect_uri, e.error_description)

Prevention

When it happens

Trigger: authorize() is called and the redirect_uri validation block raises — e.g. params.redirect_uri is malformed/None in a way that breaks validation, or client.redirect_uris contains values that make the comparison throw.

Common situations: Client sends a redirect_uri not pre-registered and an upstream/strict validation layer rejects it; tests feed params with a missing redirect_uri while client metadata requires one; encoding/whitespace differences between registered and requested URIs.

Related errors


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