agentic-community / agentic-community/mcp-gateway-registry
[Phase 4] CIMD consumer: accept CIMD URL as client_id on /authorize
- Ngôn ngữ chính
- Python
- Star
- 911
- Fork
- 234
- Merge trung bình
- 1 ngày 11 giờ
- Pull request đã merge (30 ngày)
- 62
Mô tả
# Sub-issue C: Accept CIMD URLs as `client_id` on the Registry's `/authorize` endpoint
**Parent:** #988
**Labels:** `enhancement`, `oauth`, `mcp-spec`, `authentication`, `subtask`
**Phase:** 4
**Depends on:** A, E, B
**Blocks:** none
---
## Summary
When the Registry acts as an OAuth authorization server (or as a token-proxy in front of one), accept a CIMD URL as the `client_id` parameter on `/authorize` and `/oauth/token`. Fetch the document, cache it, validate the request against it (`redirect_uris`, `grant_types`, `scope`), and issue codes / tokens against the URL-as-identity.
This is the **consumer** side of the CIMD pattern. Publisher is sub-issue B.
## Background
In the CIMD pattern the client does not pre-register with the authorization server. On the first `/authorize` request, it presents its metadata URL as `client_id`. The AS fetches the document, caches it, and from that point treats the URL as the client identity.
Claude Code already does this automatically. Once the Registry hosts its own MCP-facing OAuth surface (via the token proxy from sub-issue E), we need to consume CIMD so we're not forcing Claude Code users to also pre-register somewhere.
## Scope
### In scope
- **`/authorize` handling**: when `client_id` looks like a URL (has a scheme + host), treat it as a CIMD URL.
- Fetch over HTTPS only. Reject `http://` outside local-dev allowlist.
- Timeout + retry budget tightly bounded: 3s connect, 5s total, no retries on 4xx, one retry on 5xx.
- Validate `Content-Type: application/json`.
- Validate required fields per latest CIMD draft.
- **`redirect_uris` enforcement**: the `redirect_uri` parameter on `/authorize` MUST exactly match one of the `redirect_uris` in the fetched document. No fuzzy matching.
- **`grant_types` enforcement**: subsequent `/oauth/token` requests for this `client_id` MUST use a grant_type listed in the document.
- **`scope` enforcement**: requested scopes MUST be a subset of the scopes the document declares (intersection with the Registry's own `scopes_supported`).
- **Cache**: TTL from response `Cache-Control: max-age` (bounded 60s min, 86400s max). LRU cache of documents, ~1000 entries. Key by canonical URL.
- **Cache invalidation**: if a later `/authorize` comes in with the same `client_id` but `redirect_uri` does not match cached document, refresh the document once. If still no match, fail the request. Prevents an attacker from racing a stale cache.
- **Trust policy**: optional allowlist of allowed hostnames / regex patterns for CIMD URLs, configurable per deployment. Enterprise operators want this.
- **Observability**: structured log line for every CIMD fetch (URL, outcome, cache hit/miss, fetch latency). Metric for fetch error rate.
- **Tests**:
- Unit: URL detection, fetch with mocked HTTPS, required field validation, redirect_uri enforcement, scope intersection, cache hit/miss, cache invalidation on mismatch, allowlist enforcement.
- Integration: run a fake CIMD server, point `client_id` at it, complete an authorization code + token exchange.
### Out of scope
- Publishing our own CIMD document → sub-issue B.
- RFC 8707 `resource` audience enforcement → sub-issue E (already covers the token side).
- Pre-registered static client fallback (existing path) remains for non-CIMD clients; no changes there.
## Design notes
- The URL-shaped `client_id` detection is simple and robust: if `client_id.startswith(("http://","https://"))`, treat as CIMD; otherwise treat as a pre-registered client. Both paths coexist.
- SSRF risk is real. Enforce: HTTPS only in prod, DNS resolution to public IPs only (or allowlist), body size cap (~64 KB), content-type check, timeouts. Treat the CIMD fetcher as a hardened outbound HTTP client, not a generic one.
- Caching key MUST be the full canonical URL. Do not strip trailing slashes silently; if the spec says "fetch the URL", fetch the URL the client presented.
- Bounded concurrency on fetches to prevent cache-stampede scenarios when many clients present the same new URL at once.
## Acceptance criteria
- [ ] `client_id` values that start with `http://` (local-dev allowlist only) or `https://` are treated as CIMD URLs and fetched.
- [ ] `redirect_uri` must match an entry in the fetched `redirect_uris` exactly (no normalization).
- [ ] `grant_type` on `/oauth/token` must be in `grant_types` of the cached document.
- [ ] Requested `scope` is intersected with document scopes and Registry-supported scopes.
- [ ] Cache respects upstream `Cache-Control: max-age` bounded to [60s, 86400s]. Cache key is the full URL.
- [ ] SSRF protections: HTTPS-only in prod, public-IP-only DNS, 64 KB body cap, 5s total timeout, one 5xx retry max, content-type check.
- [ ] Optional CIMD hostname allowlist config for enterprise deployments.
- [ ] Unit tests and integration test against a fake CIMD server (happy path + each negative path).
- [ ] Observability: per-fetch structured log, metric for fetch error rate, cache hit/miss metric.
- [ ] Docs page in [docs/](docs/) explaining CIMD consumer behavior and the trust-model trade-off vs. pre-registered clients.
## Risks and open questions
- **SSRF.** See design note; this is the single highest-risk aspect. Have security review sign off before merge.
- **Draft spec drift.** Same as sub-issue B. Version-guard the consumer behind a feature flag that defaults off in a release after B lands, on in the next.
- **Enterprise skepticism.** Some operators will want CIMD fully off. Provide a clean off switch.
## References
- [CIMD draft](https://datatracker.ietf.org/doc/draft-parecki-oauth-client-id-metadata-document/)
- [OWASP SSRF cheat sheet](https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html)
- Recommendation doc §6 Phase 4: [.scratchpad/coding-assistant-oauth/recommendation-2026-05-04.md](.scratchpad/coding-assistant-oauth/recommendation-2026-05-04.md)
Hướng dẫn đóng góp
Đánh giá
Issue này chưa được đánh giá.