-
Notifications
You must be signed in to change notification settings - Fork 12
feat: auto-detect RFC 8707 resource parameter for OAuth flows #188
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: auto-detect RFC 8707 resource parameter for OAuth flows #188
Conversation
Related smart-mcp-proxy#165 Add comprehensive specification and implementation plan for automatic detection of the RFC 8707 resource parameter in OAuth flows. This enables zero-config OAuth for providers like Runlayer that require the resource parameter. Artifacts: - spec.md: Feature specification with user stories and requirements - plan.md: Implementation plan with technical context - research.md: Technical research and implementation approach - data-model.md: Entity definitions and state transitions - quickstart.md: Usage guide and troubleshooting - checklists/requirements.md: Specification quality checklist Key Decisions: - Extract resource from RFC 9728 Protected Resource Metadata - Fallback to server URL if metadata unavailable - Inject params into auth URL after mcp-go constructs it - Manual extra_params override auto-detected values
Related smart-mcp-proxy#165 Add structured task list with 39 tasks organized by user story: - Phase 1: Setup (1 task) - Phase 2: Foundational - discovery layer (5 tasks) - Phase 3: US1 - Zero-config auto-detection (15 tasks) - MVP - Phase 4: US2 - Manual override (6 tasks) - Phase 5: US3 - Token injection (4 tasks) - Phase 6: US4 - Diagnostic visibility (3 tasks) - Phase 7: Polish (5 tasks) Tasks follow TDD approach per constitution requirements.
…ection Related smart-mcp-proxy#165 Add new function that returns the full RFC 9728 Protected Resource Metadata struct including the 'resource' field needed for RFC 8707 compliance. Refactor DiscoverScopesFromProtectedResource to delegate to new function. Changes: - Add DiscoverProtectedResourceMetadata() returning *ProtectedResourceMetadata - Refactor DiscoverScopesFromProtectedResource() as wrapper for backward compat - Add comprehensive unit tests for new function Testing: - All TestDiscoverProtectedResourceMetadata_* tests pass - Existing DiscoverScopesFromProtectedResource tests still pass
Add automatic detection of RFC 8707 resource parameter from Protected Resource Metadata (RFC 9728). This enables zero-config OAuth with providers like Runlayer that require the resource parameter. Key changes: - Add CreateOAuthConfigWithExtraParams() that returns both OAuth config and auto-detected extra params including resource - Add autoDetectResource() helper that: - Makes preflight HEAD request to get WWW-Authenticate header - Extracts resource_metadata URL - Fetches Protected Resource Metadata - Uses metadata.resource or falls back to server URL - Update handleOAuthAuthorization() to accept extraParams and inject them into authorization URL - Update all 6 call sites to use new function and pass extraParams Tests: - TestCreateOAuthConfig_AutoDetectsResource: verifies resource extraction - TestCreateOAuthConfig_FallsBackToServerURL: verifies fallback behavior - E2E tests in e2e_oauth_zero_config_test.go Part of smart-mcp-proxy#165 (RFC 8707 resource auto-detection for zero-config OAuth)
Tests verify that: - T022: Manual extra_params.resource overrides auto-detected value - T023: Manual extra_params are preserved while resource is auto-detected Implementation was already complete from US1: - T024-T026: Merge logic and logging in CreateOAuthConfigWithExtraParams All tests pass: go test ./internal/oauth/... -v -run TestCreateOAuthConfig
Enable auto-detected resource parameter injection into token requests: - T029: OAuthTransportWrapper.injectFormParams() handles token exchange/refresh - T030: createOAuthConfigInternal() accepts extraParams for wrapper injection - T031: Existing TestInjectFormParams_TokenRequest covers token request injection Key changes: - CreateOAuthConfig() now delegates to createOAuthConfigInternal() - CreateOAuthConfigWithExtraParams() passes auto-detected params to internal fn - Transport wrapper uses passed extraParams instead of re-reading from config This ensures zero-config OAuth flows inject resource into all OAuth requests: - Authorization URL (via handleOAuthAuthorization) - Token exchange (via transport wrapper) - Token refresh (via transport wrapper)
MCP spec only requires POST support for the main endpoint. Use POST directly for the preflight request to get WWW-Authenticate header with resource_metadata URL. Updated all tests to use POST method in mock handlers.
3ac2303 to
eeace35
Compare
|
Tested and verified working with Runlayer/AnySource MCP servers (slack, gcal, gdrive, gsheets, gmail, glean). Resource parameter is auto-detected from RFC 9728 Protected Resource Metadata and correctly injected into OAuth flows - no manual |
|
@technicalpickles Thanks for looping me in early on this. |
|
@Dumbris thank you! would you mind cutting a release with it included? I'd love to share this with my coworkers also using runlayer/anysource. |
|
@technicalpickles the release is now published https://github.com/smart-mcp-proxy/mcpproxy-go/releases/tag/v0.10.12 |
Summary
Enable automatic detection of the RFC 8707
resourceparameter from RFC 9728 Protected Resource Metadata, eliminating manualextra_paramsconfiguration for OAuth flows with providers like Runlayer/AnySource.Related: #165 (zero-config-oauth branch work)
Problem
Runlayer/AnySource OAuth servers require the RFC 8707
resourceparameter:{"detail":[{"type":"missing","loc":["query","resource"],"msg":"Field required","input":null}]}Previously users had to manually configure this:
{ "oauth": { "extra_params": { "resource": "https://oauth.runlayer.com/api/v1/proxy/UUID/mcp" } } }Solution
Auto-detect
resourcefrom Protected Resource Metadata and inject it into:After this PR (zero configuration):
{ "name": "slack", "url": "https://oauth.runlayer.com/api/v1/proxy/UUID/mcp" }Implementation
DiscoverProtectedResourceMetadata()returning full RFC 9728 structCreateOAuthConfigWithExtraParams()returningextraParamswith auto-detected resourceextra_paramstakes precedence over auto-detected valuesmcpproxy auth statusandmcpproxy doctorshow resource detection statusKey Changes
internal/oauth/discovery.go- AddedDiscoverProtectedResourceMetadata()internal/oauth/config.go- AddedCreateOAuthConfigWithExtraParams()andautoDetectResource()internal/upstream/core/connection.go- Updated OAuth flow call sites to use new APIcmd/mcpproxy/auth_cmd.go- Added resource display to auth statusinternal/management/diagnostics.go- Updated doctor resolution messageCLAUDE.md- Added zero-config OAuth documentation sectionPlanning Artifacts
Status
Test Plan
DiscoverProtectedResourceMetadata()-discovery_test.goCreateOAuthConfig()-config_test.goe2e_oauth_zero_config_test.go./scripts/run-linter.sh)./scripts/run-all-tests.sh)