-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Description
Type
Enhancement
Problem / Value
When Roo connects to a protected HTTP-based MCP server, it should initiate a standard OAuth 2.1 flow automatically so users can securely use enterprise/protected MCP servers. Today, Roo does not consistently trigger this flow after a 401 + WWW-Authenticate challenge, which blocks connections to compliant servers.
Context
- Original report: “Roo does not initiate the OAuth flow if the remote MCP server implements Authorization.”
- Example setup from the report: fastmcp with Azure provider; server returns 401 with WWW-Authenticate and advertises OAuth resource metadata.
- User environment noted in the report:
- App Version: 3.25.20
- OS: macOS Sequoia 15.5
- VS Code: 1.103.0 (Universal)
- API Provider: OpenAI Compatible
- Model: Claude Sonnet 4
Desired Behavior (at a high level)
Roo should:
1 Parse HTTP 401 WWW-Authenticate to discover the OAuth 2.0 Protected Resource Metadata (RFC 9728).
2) Fetch the resource metadata (/.well-known/oauth-protected-resource) to obtain authorization_servers and select one.
3) Discover authorization server metadata (RFC 8414 and OpenID Connect Discovery 1.0) using the required precedence for issuers with/without path components.
4) If supported, perform Dynamic Client Registration (RFC 7591) to obtain a client_id (and client_secret if confidential).
5) Start Authorization Code + PKCE (S256), including the resource parameter (RFC 8707) in both authorization and token requests.
6) Exchange the authorization code for tokens, store them securely, then retry MCP requests with Authorization: Bearer .
7) Handle token refresh/expiry and error conditions per spec.
Implementation Notes (standards summary for assignees)
-
Roles
- MCP Server: OAuth 2.1 Resource Server
- Roo (MCP Client): OAuth 2.1 Client
- Authorization Server: issues access tokens for use at the MCP server
-
Resource Server Discovery (RFC 9728)
- On 401, parse WWW-Authenticate and obtain resource metadata URL
- GET /.well-known/oauth-protected-resource
- Use authorization_servers (may be multiple; client selects per RFC guidance)
-
Authorization Server Discovery (RFC 8414 + OIDC Discovery 1.0)
- Issuer with path (e.g., https://auth.example.com/tenant1):
- /.well-known/oauth-authorization-server/tenant1
- /.well-known/openid-configuration/tenant1
- /tenant1/.well-known/openid-configuration
- Issuer without path (e.g., https://auth.example.com):
- /.well-known/oauth-authorization-server
- /.well-known/openid-configuration
- MUST attempt in this priority and support both specs
- Issuer with path (e.g., https://auth.example.com/tenant1):
-
Dynamic Client Registration (RFC 7591) [SHOULD]
- POST /register to obtain client_id (and client_secret if confidential)
- If not supported, Roo needs config/UI to provide client_id(/secret)
-
Authorization Code + PKCE (OAuth 2.1)
- PKCE S256 required; verify PKCE support via AS metadata:
- RFC 8414: if code_challenge_methods_supported is absent → refuse
- OIDC Discovery: verify code_challenge_methods_supported present → if absent → refuse
- Redirect URIs must be HTTPS or localhost
- Include state; open browser for authorization
- PKCE S256 required; verify PKCE support via AS metadata:
-
Resource Indicators (RFC 8707) [MUST]
- Include resource (canonical URI of the MCP server) in BOTH authorization and token requests
- Scheme-inclusive, no fragments; prefer no trailing slash unless required
- Examples: https://mcp.example.com, https://mcp.example.com/mcp, https://mcp.example.com:8443
-
Token Usage and Validation
- Authorization: Bearer on every HTTP request (never in query string)
- Resource server validates tokens per OAuth 2.1 §5.2 and audience per RFC 8707
- No token passthrough to upstream APIs; obtain separate tokens if the MCP server calls upstream APIs
-
Error Handling
- 401 Unauthorized: auth required/invalid or expired token (use WWW-Authenticate)
- 403 Forbidden: insufficient scope/permissions
- 400 Bad Request: malformed auth request
-
Security Considerations (Required)
- HTTPS for AS endpoints; redirect URIs HTTPS or localhost
- PKCE S256 mandatory with metadata verification as above
- Use/verify state to mitigate open redirection
- Secure token storage; prefer short-lived access tokens; refresh-token rotation for public clients
- Enforce audience validation; forbid token passthrough (“confused deputy”)
Acceptance Criteria
-
After a 401 with WWW-Authenticate from an HTTP MCP server:
- Roo fetches RFC 9728 resource metadata and selects an authorization server
- Roo discovers AS metadata using the ordered endpoints above (RFC 8414 + OIDC Discovery)
- If available, Roo performs RFC 7591 dynamic client registration and persists client details
- Roo runs Authorization Code + PKCE (S256) and:
- Includes resource in both authorization and token requests
- Verifies code_challenge_methods_supported via metadata; refuses if absent or S256 unsupported
- Roo securely stores tokens, injects Authorization: Bearer on all MCP HTTP calls, refreshes when needed
- Roo retries the original MCP request after successful token acquisition
- Roo surfaces clear UX for 400/401/403 and auth prompts
-
Tests
- Unit: header parsing (WWW-Authenticate), resource metadata fetch/parse, AS discovery fallback ordering, PKCE generation/verification, resource parameter inclusion, token header injection, error handling
- Integration: end-to-end against a mock/proxy AS + MCP resource server
- Manual QA: documented flow with a real provider (e.g., fastmcp Azure)
Non-Goals
- Proprietary flows outside OAuth 2.1, RFC 9728, RFC 8414/OIDC Discovery, RFC 7591, RFC 8707
- Token passthrough to upstream APIs
Open Questions
- Should Roo expose a small UI for manual client_id(/secret) entry when dynamic registration is unavailable?
- What secure storage mechanism will Roo use for tokens/refresh tokens across platforms?
References
- MCP Authorization draft: https://modelcontextprotocol.io/specification/draft/basic/authorization
- OAuth 2.1 (draft-ietf-oauth-v2-1-13): https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13
- OAuth 2.0 Protected Resource Metadata (RFC 9728): https://datatracker.ietf.org/doc/html/rfc9728
- OAuth 2.0 Authorization Server Metadata (RFC 8414): https://datatracker.ietf.org/doc/html/rfc8414
- OpenID Connect Discovery 1.0: https://openid.net/specs/openid-connect-discovery-1_0.html
- OAuth 2.0 Dynamic Client Registration (RFC 7591): https://datatracker.ietf.org/doc/html/rfc7591
- Resource Indicators (RFC 8707): https://www.rfc-editor.org/rfc/rfc8707.html
- Security best practices (token passthrough): https://modelcontextprotocol.io/specification/draft/basic/security_best_practices#token-passthrough
Proposed Labels: feature request; Issue - Needs Scoping
GH_BODY
)
Metadata
Metadata
Assignees
Labels
Type
Projects
Status