Skip to content

Conversation

@JAORMX
Copy link
Collaborator

@JAORMX JAORMX commented Sep 18, 2025

Summary

This PR fixes authentication failures with remote MCP servers where the OAuth/OIDC issuer identifier differs from the metadata discovery URL, while maintaining strict security validation.

Problem

Remote MCP servers like Atlassian return different issuers than their metadata URLs:

  • Metadata URL: https://mcp.atlassian.com
  • Actual issuer: https://atlassian-remote-mcp-production.workers.dev

This pattern is explicitly allowed by RFC 8414 Section 3 but was causing authentication failures in ToolHive.

Solution

Context-Aware Issuer Validation

Implemented a context-aware approach using the IsResourceMetadataDiscovery flag to distinguish between:

  1. Resource Metadata Discovery Context (IsResourceMetadataDiscovery = true)

    • Used when discovering OAuth endpoints from resource metadata URLs
    • Allows issuer mismatch per RFC 8414 and RFC 9728
    • Common pattern for providers like Atlassian, Stripe, etc.
    • Issuer validation deferred to token validation phase
  2. Direct Issuer Specification (IsResourceMetadataDiscovery = false)

    • Used when issuer is directly specified
    • Enforces strict issuer match for security
    • Prevents potential security vulnerabilities

Key Changes

pkg/auth/discovery/discovery.go

  • Added IsResourceMetadataDiscovery field to OAuthFlowConfig
  • Modified getDiscoveryDocument() to conditionally use DiscoverActualIssuer() based on context
  • Added comprehensive documentation explaining the security implications

pkg/runner/remote_auth.go

  • Sets IsResourceMetadataDiscovery = true when using discovered endpoints
  • Properly tracks context from resource metadata discovery

pkg/auth/oauth/oidc.go

  • DiscoverActualIssuer() function skips issuer validation when appropriate
  • discoverOIDCEndpointsWithClientAndValidation() accepts validateIssuer parameter

Security Considerations

Maintained Security Protections

  • ✅ HTTPS enforcement for all non-localhost connections
  • ✅ Endpoint URL validation blocks malicious URIs (data:, file:, javascript:)
  • ✅ Response size limiting and content-type validation
  • ✅ PKCE and state parameters protect the OAuth flow
  • ✅ Token issuer claims validated during token exchange
  • ✅ Strict issuer validation for direct issuer specification

Attack Vector Protection

Added comprehensive tests confirming protection against:

  • SSRF attacks: Malicious redirect attempts blocked
  • XSS attacks: JavaScript URIs rejected
  • Data exfiltration: Data URIs blocked
  • File access: File URIs rejected
  • Redirect attacks: Invalid redirect URIs blocked

Testing

New Test Coverage

  1. Issuer Mismatch Tests (pkg/auth/discovery/discovery_issuer_mismatch_test.go)

    • Tests Atlassian pattern (metadata URL != issuer)
    • Tests Stripe pattern (similar mismatch scenario)
    • Validates context-aware behavior
  2. Security Validation Tests (pkg/auth/oauth/oidc_malicious_scenarios_test.go)

    • Tests protection against various malicious URIs
    • Validates HTTPS enforcement
    • Tests response validation
  3. Context-Aware Validation Tests (pkg/auth/oauth/oidc_issuer_validation_test.go)

    • Tests behavior with IsResourceMetadataDiscovery = true
    • Tests behavior with IsResourceMetadataDiscovery = false
    • Validates security boundaries

Test Results

  • ✅ All new tests pass
  • ✅ All existing tests continue to pass
  • ✅ Linting clean
  • ✅ No race conditions detected

RFC Compliance

This implementation aligns with:

  • RFC 8414: OAuth 2.0 Authorization Server Metadata - allows issuer mismatch
  • RFC 9728: OAuth 2.0 Protected Resource Metadata - resource metadata discovery pattern

Fixes

Fixes #1957

Review Notes

The solution balances the need to support legitimate issuer mismatches (as per RFC 8414) while maintaining security against potential attacks. The context-aware approach ensures we only relax validation where it's explicitly expected and safe to do so.

@codecov
Copy link

codecov bot commented Sep 18, 2025

Codecov Report

❌ Patch coverage is 57.69231% with 11 lines in your changes missing coverage. Please review.
✅ Project coverage is 47.07%. Comparing base (3a73947) to head (2987ed5).
⚠️ Report is 3 commits behind head on main.

Files with missing lines Patch % Lines
pkg/runner/remote_auth.go 0.00% 9 Missing ⚠️
pkg/auth/discovery/discovery.go 88.23% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1959      +/-   ##
==========================================
+ Coverage   47.00%   47.07%   +0.07%     
==========================================
  Files         223      223              
  Lines       27679    27704      +25     
==========================================
+ Hits        13011    13043      +32     
+ Misses      13670    13665       -5     
+ Partials      998      996       -2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@JAORMX JAORMX marked this pull request as draft September 18, 2025 12:52
@JAORMX JAORMX force-pushed the fix/issue-1957-oidc-issuer-mismatch branch 2 times, most recently from c7edb49 to f9d3710 Compare September 18, 2025 13:41
flowConfig.RegistrationEndpoint = authServerInfo.RegistrationEndpoint
// Mark that we're in resource metadata discovery context
// This allows issuer mismatch which is legitimate for resource metadata
flowConfig.IsResourceMetadataDiscovery = true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My only concern is when we derive the issuer from Remote URL, because Realm and resource_metadata do not include issuer

…aware validation

This change fixes authentication failures with remote MCP servers where
the OAuth/OIDC issuer identifier differs from the metadata discovery URL,
while maintaining strict security validation.

Problem:
- Remote MCP servers like Atlassian return different issuers than their metadata URLs
  - Metadata URL: https://mcp.atlassian.com
  - Actual issuer: https://atlassian-remote-mcp-production.workers.dev
- This pattern is allowed by RFC 8414 but was causing authentication failures

Solution:
- Implemented context-aware issuer validation using IsResourceMetadataDiscovery flag
- Resource metadata discovery context: allows issuer mismatch (RFC 8414 compliant)
- Direct issuer specification: enforces strict issuer match (security critical)
- Modified getDiscoveryDocument() to use appropriate validation based on context

Security:
- HTTPS enforcement for all non-localhost connections
- Endpoint URL validation blocks malicious URIs (data:/file:/javascript:)
- Response size limiting and content-type validation
- Issuer validation deferred to token validation phase for resource metadata
- Strict issuer validation maintained for direct issuer specification

Testing:
- Added comprehensive test coverage for issuer mismatch scenarios
- Added security validation tests for various attack vectors
- Tests confirm protection against SSRF, XSS, and redirect attacks
- All existing tests continue to pass

This approach balances the need to support legitimate issuer mismatches
(as per RFC 8414) while maintaining security against potential attacks.

Fixes #1957
@JAORMX JAORMX force-pushed the fix/issue-1957-oidc-issuer-mismatch branch from f9d3710 to 2987ed5 Compare September 18, 2025 13:46
@JAORMX
Copy link
Collaborator Author

JAORMX commented Sep 18, 2025

The implementation handles the issuer mismatch scenario where OAuth/OIDC providers return a different issuer in their metadata than the URL used to fetch that metadata. This is explicitly allowed by RFC 8414 and used by providers like Atlassian.

Key changes:

  • Added IsResourceMetadataDiscovery flag to distinguish between resource metadata discovery (allows mismatch) and direct issuer specification (strict validation)
  • Modified getDiscoveryDocument() to use context-aware validation
  • Set the flag when issuer is derived from remote URL rather than explicitly configured

Testing:
Confirmed the Atlassian remote MCP server now authenticates successfully:

INFO Discovered actual issuer: https://atlassian-remote-mcp-production.atlassian-remote-mcp-server-production.workers.dev (from metadata URL: https://mcp.atlassian.com)
INFO Successfully registered OAuth client dynamically

Security: Strict validation remains for explicitly configured issuers. Only resource metadata discovery contexts allow issuer mismatch per RFC 8414.

@JAORMX JAORMX closed this Sep 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OIDC issuer mismatch prevents authentication with Atlassian remote MCP server

3 participants