PrefectHQ/fastmcp · error · ValueError
Either client_secret or jwt_signing_key must be provided. jw
Error message
Either client_secret or jwt_signing_key must be provided. jwt_signing_key is required when client_secret is omitted (e.g., for PKCE public clients).
What it means
OIDCProxy requires either a client_secret (confidential client) or a jwt_signing_key (for secret-less flows such as PKCE public clients or private_key_jwt) and raises ValueError if neither is provided.
Source
Thrown at fastmcp_slim/fastmcp/server/auth/oidc_proxy.py:356
MCP clients can't refresh gracefully (e.g. `mcp-remote`).
token_expiry_threshold_seconds: Number of seconds before actual expiry to consider
a token as expired (default 0). Prevents race conditions where a token
passes the expiry check but expires before the next operation completes.
enable_cimd: Whether to enable CIMD (Client ID Metadata Document) client support.
When True, clients can use their metadata document URL as client_id instead of
Dynamic Client Registration. Default is True.
identity_assertion: Optional SEP-990 identity assertion (ID-JAG) configuration.
When provided, the token endpoint accepts the RFC 7523 jwt-bearer grant
carrying an ID-JAG issued by one of the configured trusted issuers.
"""
if not config_url:
raise ValueError("Missing required config URL")
if not client_id:
raise ValueError("Missing required client id")
if not client_secret and not jwt_signing_key:
raise ValueError(
"Either client_secret or jwt_signing_key must be provided. "
"jwt_signing_key is required when client_secret is omitted "
"(e.g., for PKCE public clients)."
)
if not base_url:
raise ValueError("Missing required base URL")
# Validate that verifier-specific parameters are not used with custom verifier
if token_verifier is not None:
if algorithm is not None:
raise ValueError(
"Cannot specify 'algorithm' when providing a custom token_verifier. "
"Configure the algorithm on your token verifier instead."
)
if required_scopes is not None:
raise ValueError(
"Cannot specify 'required_scopes' when providing a custom token_verifier. "View on GitHub (pinned to 1f02114297)
Solutions
- Provide client_secret for a confidential client, or provide jwt_signing_key if the client is public/PKCE or uses JWT-based auth
- Verify the secret env var is non-empty (empty strings are treated as missing)
- If intentional secret-less flow, generate/load the jwt_signing_key before construction
Example fix
// before proxy = OIDCProxy(config_url=..., client_id="app") # neither secret nor key // after proxy = OIDCProxy(config_url=..., client_id="app", client_secret=os.environ["OIDC_CLIENT_SECRET"])
Defensive patterns
Strategy: validation
Validate before calling
if not client_secret and not jwt_signing_key:
raise ValueError("provide client_secret (confidential) or jwt_signing_key (public/PKCE)") Try / catch
try:
proxy = OIDCProxy(config_url=..., client_id=..., client_secret=secret, jwt_signing_key=key)
except ValueError as e:
logger.error("credential configuration invalid: %s", e)
raise SystemExit(1) Prevention
- Decide confidential-vs-public client up front and configure exactly one credential path
- Treat empty-string env values as missing (strip and check)
- Document in your deploy checklist: secret or signing key is mandatory
When it happens
Trigger: Constructing OIDCProxy(...) with client_secret omitted/empty AND jwt_signing_key omitted — e.g. setting up a public client but forgetting jwt_signing_key, or a secret env var that is empty string (falsy).
Common situations: PKCE public-client setups missing the signing key; deployed without the client secret mounted; empty-string secrets from placeholder env values that fail the truthiness check.
Related errors
- OIDC discovery document for issuer {issuer!r} has no jwks_ur
- Missing required configuration metadata: {attr}
- Invalid URL for configuration metadata: {attr}
- Missing required config URL
- Missing required client id
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/977a3fb24b350f67.
Report an issue: GitHub.