|
| 1 | +# Code Review: PR #188 - Auto-detect RFC 8707 Resource Parameter for OAuth |
| 2 | + |
| 3 | +**Date**: 2025-12-10 |
| 4 | +**PR**: https://github.com/smart-mcp-proxy/mcpproxy-go/pull/188 |
| 5 | +**Reviewer**: Claude Code |
| 6 | + |
| 7 | +## Overview |
| 8 | + |
| 9 | +This PR implements automatic detection of the RFC 8707 `resource` parameter from RFC 9728 Protected Resource Metadata, enabling zero-configuration OAuth for providers like Runlayer/AnySource. This is a well-structured feature addition that improves user experience by eliminating manual `extra_params` configuration. |
| 10 | + |
| 11 | +## Summary of Changes |
| 12 | + |
| 13 | +| File | Type | Description | |
| 14 | +|------|------|-------------| |
| 15 | +| `internal/oauth/config.go` | New API | Added `CreateOAuthConfigWithExtraParams()` and `autoDetectResource()` | |
| 16 | +| `internal/oauth/discovery.go` | Enhancement | Added `DiscoverProtectedResourceMetadata()` | |
| 17 | +| `internal/upstream/core/connection.go` | Integration | Updated 4 call sites to use new API | |
| 18 | +| `cmd/mcpproxy/auth_cmd.go` | UX | Added resource status display | |
| 19 | +| `internal/management/diagnostics.go` | UX | Updated doctor resolution message | |
| 20 | +| `CLAUDE.md` | Docs | Comprehensive documentation | |
| 21 | +| Tests | Verification | Extensive unit and E2E tests | |
| 22 | + |
| 23 | +--- |
| 24 | + |
| 25 | +## Positives |
| 26 | + |
| 27 | +### 1. Clean API Design |
| 28 | +The new `CreateOAuthConfigWithExtraParams()` function returns both the config and extraParams, enabling the connection layer to inject params into the authorization URL. The backward-compatible `CreateOAuthConfig()` is preserved for existing callers. |
| 29 | + |
| 30 | +### 2. Proper Priority Order |
| 31 | +```go |
| 32 | +// Resource auto-detection logic (in priority order): |
| 33 | +// 1. Manual extra_params.resource from config (highest priority) |
| 34 | +// 2. Auto-detected resource from RFC 9728 Protected Resource Metadata |
| 35 | +// 3. Fallback to server URL if metadata unavailable |
| 36 | +``` |
| 37 | + |
| 38 | +This correctly preserves backward compatibility - manual overrides always win. |
| 39 | + |
| 40 | +### 3. Excellent Test Coverage |
| 41 | +- Unit tests for `DiscoverProtectedResourceMetadata()` with error cases |
| 42 | +- Unit tests for resource auto-detection and manual override |
| 43 | +- E2E test validating full metadata discovery flow |
| 44 | +- Tests for parameter merging behavior |
| 45 | + |
| 46 | +### 4. Good Documentation |
| 47 | +- CLAUDE.md updated with clear explanation and examples |
| 48 | +- Inline code comments explain RFC references |
| 49 | +- Diagnostic commands documented for troubleshooting |
| 50 | + |
| 51 | +--- |
| 52 | + |
| 53 | +## Issues and Suggestions |
| 54 | + |
| 55 | +### 1. **Network Request in Config Creation** (Medium Risk) - FIXED |
| 56 | + |
| 57 | +```go:internal/oauth/config.go |
| 58 | +func autoDetectResource(serverConfig *config.ServerConfig, logger *zap.Logger) string { |
| 59 | + resp, err := http.Post(serverConfig.URL, "application/json", strings.NewReader("{}")) |
| 60 | +``` |
| 61 | +
|
| 62 | +**Concern**: The `CreateOAuthConfigWithExtraParams()` function makes a synchronous HTTP POST request during config creation. This can cause: |
| 63 | +- Slowdown during startup if the server is slow/unreachable |
| 64 | +- Potential timeout issues affecting connection initialization |
| 65 | +- No timeout specified on the `http.Post` call |
| 66 | +
|
| 67 | +**Fix**: Added 5-second timeout to preflight request client. |
| 68 | +
|
| 69 | +### 2. **Fallback Logic Inconsistency** (Low Risk) - FIXED |
| 70 | +
|
| 71 | +In `autoDetectResource()`: |
| 72 | +- On network error: returns `serverConfig.URL` (fallback) |
| 73 | +- On non-401 response: returns `""` (no resource) |
| 74 | +- On 401 without metadata URL: returns `serverConfig.URL` (fallback) |
| 75 | +
|
| 76 | +The non-401 case returning empty string seems correct (server doesn't require OAuth), but the behavior isn't immediately obvious from the code. |
| 77 | +
|
| 78 | +**Fix**: Added clarifying comment explaining why non-401 returns empty. |
| 79 | +
|
| 80 | +### 3. **Unused Variable in E2E Test** - FIXED |
| 81 | +
|
| 82 | +```go:internal/server/e2e_oauth_zero_config_test.go |
| 83 | +ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) |
| 84 | +defer cancel() |
| 85 | +``` |
| 86 | +
|
| 87 | +The `ctx` variable is created but never passed to the discovery function. |
| 88 | +
|
| 89 | +**Fix**: Removed unused context variable and related check. |
| 90 | +
|
| 91 | +### 4. **Minor: Unused import check** - FIXED |
| 92 | +
|
| 93 | +```go:internal/server/e2e_oauth_zero_config_test.go |
| 94 | +// compile-time check to silence unused import warning |
| 95 | +var _ = zap.NewNop |
| 96 | +``` |
| 97 | +
|
| 98 | +**Fix**: Removed unused zap import and dummy reference. |
| 99 | +
|
| 100 | +--- |
| 101 | +
|
| 102 | +## Security Considerations |
| 103 | +
|
| 104 | +**Positive**: The implementation correctly: |
| 105 | +- Respects manual configuration over auto-detected values |
| 106 | +- Masks sensitive params in logs (existing `maskExtraParams` function) |
| 107 | +- Uses standard HTTP methods for discovery |
| 108 | +
|
| 109 | +**Note**: The POST request with empty body `{}` to detect 401 is per MCP spec. Consider documenting this as it might appear suspicious in network logs. |
| 110 | +
|
| 111 | +--- |
| 112 | +
|
| 113 | +## Performance Considerations |
| 114 | +
|
| 115 | +The preflight POST request adds latency to connection establishment. For servers that don't advertise RFC 9728 metadata, this is overhead with no benefit. Consider: |
| 116 | +- Caching metadata discovery results |
| 117 | +- Making discovery async (non-blocking) |
| 118 | +
|
| 119 | +However, this is likely acceptable for v1 since it only happens during initial connection. |
| 120 | +
|
| 121 | +--- |
| 122 | +
|
| 123 | +## Verdict |
| 124 | +
|
| 125 | +**Approved with minor fixes applied.** |
| 126 | +
|
| 127 | +This is a well-implemented feature with good test coverage and documentation. The code follows project conventions and the API design is clean. |
| 128 | +
|
| 129 | +### Fixes Applied: |
| 130 | +1. Added timeout to `http.Post` call in `autoDetectResource()` |
| 131 | +2. Added clarifying comment for non-401 return behavior |
| 132 | +3. Removed unused `ctx` variable in E2E test |
| 133 | +4. Removed unused zap import workaround in E2E test |
0 commit comments