agentic-community / agentic-community/mcp-gateway-registry

oauth_user egress requires client_secret, so a public PKCE client cannot be configured — intentional?

Ouverte
#1,604 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub
Langage dominant
Python
Étoiles
911
Forks
234
Merge moyen
1 j 11 h
PR mergées (30 j)
62

Description

## Question

Configuring `oauth_user` egress requires a `client_secret` unconditionally, which makes a **public PKCE client** impossible to configure. Is that deliberate?

`registry/api/egress_auth_routes.py:654-655`:

```python
if not eo["client_secret_encrypted"]:
raise HTTPException(status.HTTP_400_BAD_REQUEST, detail="client_secret required")
```

I am filing this as a question rather than a bug because "we only support confidential clients" is a coherent posture for a server-side component that can hold a secret safely, and PKCE + a secret is a legitimate belt-and-braces pattern. But the code carries no comment either way, which is notable in a file that documents its other security decisions carefully (the SSRF rationale in `_post_token` a few lines away, for instance).

## What points toward it being unintended

- **PKCE exists so public clients need no secret** (RFC 7636), and the registry implements it fully: `generate_pkce_verifier`, `pkce_challenge_s256`, and `OAuthProviderConfig.use_pkce` defaulting to `True`.
- **The engine does not require one.** `_build_token_request` just interpolates whatever it is handed (`data["client_secret"] = client_secret`); nothing downstream validates it. Only the config-write path does.
- **The generated authorize URL already includes `code_challenge_method=S256`.** So the registry does PKCE *and* demands the secret PKCE is designed to replace.

## Concrete case

Salesforce Hosted MCP (Headless 360). Salesforce's own setup docs describe "Require Secret for Web Server Flow" as **discouraged** for clients that cannot store a secret securely, so a public External Client App is a normal configuration there.

I verified such a client genuinely has no secret: a `refresh_token` grant against `https://login.salesforce.com/services/oauth2/token` with `client_id` only returned **HTTP 200** with `scope: refresh_token mcp_api`, and the resulting token worked against the MCP endpoint (`initialize` + `tools/list` both 200).

Attempting to configure it:

```
POST /api/servers/salesforce-headless-360/egress-auth
{"egress_auth_mode":"oauth_user","egress_provider":"custom","client_id":"",
"scopes":["mcp_api","refresh_token"],
"custom_authorize_url":"...","custom_token_url":"..."}

-> HTTP 400 {"detail":"client_secret required"}
```

The identical request with a `client_secret` added returns **200**, and the flow then initiates correctly (`/api/egress-auth/initiate` → 200, authorize URL with `code_challenge_method=S256` and the registry's own callback). So the secret is the only blocker.

## If intentional

Worth a comment at that line plus a clearer error — `"client_secret required"` does not hint that public clients are unsupported *by design*, so the natural reading is that something is misconfigured. A line in the egress docs would help too.

## If not

Gating the check on the resolved provider's `use_pkce` would cover it: required when PKCE is off, optional when on.

## What I have not verified

I have **not** proven a full end-to-end flow succeeds without a secret — only the refresh leg, tested directly against Salesforce rather than through the gateway. The authorize leg needs the gateway callback allowlisted in the provider's app, which I have not completed. So I cannot claim that removing the check is sufficient, only that the current check is what stops the configuration being stored.

Happy to send a patch if the gating approach is the preferred direction.

Guide de contribution

Ouvrir le guide de contribution

Évaluation

Cette issue n'a pas encore été évaluée.

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.