Skip to content

[FEATURE][AUTH]: Infer identity provider info for onboarded MCP servers #1435

@VRamakrishna

Description

@VRamakrishna

🧭 Epic

Title: Infer Identity Provider Information for Onboarded MCP Servers

Goal: Automatically discover OAuth 2.0 Authorization Server metadata (RFC 8414) for MCP servers, enabling seamless authentication without manual configuration of issuer URLs and endpoints.

Why now:

  • Onboarding MCP servers requires manual configuration of OAuth endpoints
  • RFC 8414 provides a standard way to discover authorization server metadata
  • Reduces friction when connecting to OAuth-protected MCP servers
  • Enables Dynamic Client Registration (RFC 7591) for automated client setup
  • Current codebase has foundation in dcr_service.py but needs broader integration

📖 User Stories

US-1: Developer - Auto-Discover OAuth Endpoints

As a: Developer onboarding an OAuth-protected MCP server

I want: The gateway to automatically discover the authorization server's endpoints

So that: I don't need to manually configure token endpoint, authorization endpoint, etc.

Acceptance Criteria:

Scenario: Discover AS metadata from issuer URL
  Given an MCP server protected by OAuth with issuer "https://auth.example.com"
  When I register the gateway with the issuer URL
  Then the gateway should fetch /.well-known/oauth-authorization-server
  And automatically populate token_endpoint, authorization_endpoint, jwks_uri
  And store the discovered metadata for future use

Scenario: Fallback to OIDC discovery
  Given an OAuth server that doesn't support RFC 8414
  When RFC 8414 discovery fails
  Then the gateway should try /.well-known/openid-configuration
  And use OIDC metadata if available

Scenario: Handle discovery failure gracefully
  Given an OAuth server with no discovery endpoints
  When both RFC 8414 and OIDC discovery fail
  Then the gateway should prompt for manual endpoint configuration
  And log the discovery failure for debugging

Technical Requirements:

  • Use existing DCRService.discover_as_metadata() from mcpgateway/services/dcr_service.py
  • Cache discovered metadata with configurable TTL
  • Support both RFC 8414 and OIDC discovery paths
US-2: Admin - Dynamic Client Registration

As a: Platform Administrator

I want: The gateway to automatically register as an OAuth client when DCR is supported

So that: I don't need to manually create OAuth applications in the identity provider

Acceptance Criteria:

Scenario: Auto-register via DCR
  Given an authorization server supports Dynamic Client Registration
  When I configure a new gateway with OAuth authentication
  Then the gateway should check if registration_endpoint is available
  And automatically register using DCR if supported
  And store the client_id and client_secret securely

Scenario: Manual client setup when DCR unavailable
  Given an authorization server doesn't support DCR
  When I configure a new gateway with OAuth
  Then the gateway should prompt for client_id and client_secret
  And provide instructions for manual OAuth app setup
  And validate the credentials before saving

Scenario: DCR with initial access token
  Given an authorization server requires authentication for DCR
  When I have an initial_access_token
  Then the gateway should use it to register the client
  And handle token expiration gracefully

Technical Requirements:

  • Check for registration_endpoint in AS metadata
  • Implement RFC 7591 client registration request
  • Support initial_access_token for protected registration
  • Store credentials encrypted in database
US-3: Operator - Cache and Refresh Metadata

As a: Platform Operator

I want: Discovered metadata cached with automatic refresh

So that: The gateway doesn't make discovery requests on every auth operation

Acceptance Criteria:

Scenario: Metadata is cached
  Given I have discovered AS metadata for "https://auth.example.com"
  When I make multiple OAuth requests
  Then the cached metadata should be used
  And no additional discovery requests should be made

Scenario: Metadata refresh on expiry
  Given cached metadata has expired (TTL exceeded)
  When an OAuth operation is performed
  Then the metadata should be re-discovered
  And the cache should be updated with new metadata

Scenario: Handle metadata changes
  Given the authorization server's endpoints change
  When the cached metadata is refreshed
  Then the new endpoints should be used
  And connections using old endpoints should fail gracefully

Technical Requirements:

  • Use existing _metadata_cache in dcr_service.py
  • Configurable TTL via DCR_METADATA_CACHE_TTL (default: 3600s)
  • Background refresh before expiry

🏗 Architecture

Discovery Flow

sequenceDiagram
    participant Admin as Admin UI
    participant Gateway as MCP Gateway
    participant DCR as DCR Service
    participant Cache as Metadata Cache
    participant AS as Authorization Server

    Admin->>Gateway: Register MCP server (issuer URL)
    Gateway->>DCR: discover_as_metadata(issuer)
    DCR->>Cache: Check cache for issuer
    
    alt Cache hit
        Cache-->>DCR: Return cached metadata
    else Cache miss
        DCR->>AS: GET /.well-known/oauth-authorization-server
        alt RFC 8414 supported
            AS-->>DCR: AS metadata
        else RFC 8414 not supported
            DCR->>AS: GET /.well-known/openid-configuration
            AS-->>DCR: OIDC metadata
        end
        DCR->>Cache: Store metadata (TTL)
    end
    
    DCR-->>Gateway: AS metadata
    
    alt DCR supported
        Gateway->>DCR: register_client(metadata)
        DCR->>AS: POST /register
        AS-->>DCR: client_id, client_secret
        Gateway->>Gateway: Store credentials (encrypted)
    else DCR not supported
        Gateway->>Admin: Prompt for credentials
    end
Loading

Metadata Storage

classDiagram
    class ASMetadata {
        +issuer: str
        +authorization_endpoint: str
        +token_endpoint: str
        +registration_endpoint: Optional[str]
        +jwks_uri: str
        +scopes_supported: list[str]
        +grant_types_supported: list[str]
        +discovered_at: datetime
        +expires_at: datetime
    }
    
    class OAuthCredentials {
        +gateway_id: str
        +client_id: str
        +client_secret_encrypted: str
        +scopes: list[str]
        +registered_via: str
        +created_at: datetime
    }
Loading

📋 Implementation Tasks

Phase 1: Discovery Enhancement

  • Extend DCRService.discover_as_metadata() to return typed ASMetadata object
  • Add automatic fallback from RFC 8414 to OIDC discovery
  • Add comprehensive error handling with specific error types
  • Log discovery attempts and failures for debugging

Phase 2: Cache Management

  • Make metadata cache TTL configurable via DCR_METADATA_CACHE_TTL
  • Add background refresh before expiry (proactive refresh)
  • Add cache invalidation endpoint for admin use
  • Add metrics for cache hits/misses

Phase 3: Gateway Integration

  • Auto-trigger discovery when registering OAuth-protected gateway
  • Populate gateway OAuth config from discovered metadata
  • Store discovered endpoints in gateway record
  • Update Admin UI to show discovered vs manual endpoints

Phase 4: Dynamic Client Registration

  • Implement RFC 7591 client registration in DCRService
  • Support initial_access_token for protected registration
  • Store client credentials encrypted in database
  • Handle registration errors gracefully

Phase 5: Admin UI Updates

  • Add "Discover" button in gateway OAuth configuration
  • Show discovered endpoints (read-only)
  • Prompt for credentials when DCR unavailable
  • Show DCR status indicator

Phase 6: Testing

  • Unit tests for RFC 8414 discovery
  • Unit tests for OIDC fallback
  • Unit tests for DCR registration
  • Integration tests with Keycloak
  • Integration tests with Auth0
  • Integration tests with Azure AD

⚙️ Configuration Examples

Environment Variables

# OAuth Discovery (RFC 8414)
OAUTH_DISCOVERY_ENABLED=true
DCR_METADATA_CACHE_TTL=3600  # Cache TTL in seconds

# DCR Settings
DCR_ENABLED=true
DCR_DEFAULT_SCOPES="openid profile email"

Gateway with Auto-Discovery

{
  "name": "OAuth Protected MCP Server",
  "url": "https://mcp.example.com/sse",
  "authentication": {
    "type": "oauth2",
    "issuer": "https://auth.example.com",
    "auto_discover": true
  }
}

Discovered Metadata (stored)

{
  "issuer": "https://auth.example.com",
  "authorization_endpoint": "https://auth.example.com/authorize",
  "token_endpoint": "https://auth.example.com/token",
  "registration_endpoint": "https://auth.example.com/register",
  "jwks_uri": "https://auth.example.com/.well-known/jwks.json",
  "scopes_supported": ["openid", "profile", "email", "mcp:tools"],
  "grant_types_supported": ["authorization_code", "client_credentials"],
  "discovered_at": "2026-01-25T12:00:00Z",
  "expires_at": "2026-01-25T13:00:00Z"
}

✅ Success Criteria

  • RFC 8414 discovery works for standard OAuth servers
  • OIDC fallback works when RFC 8414 not supported
  • Metadata cached with configurable TTL
  • DCR registration works when supported
  • Admin UI prompts for credentials when DCR unavailable
  • Credentials stored encrypted in database
  • Works with Keycloak, Auth0, Azure AD, Okta
  • Graceful error handling for all failure modes

🏁 Definition of Done

  • RFC 8414 discovery implemented in DCRService
  • OIDC discovery fallback implemented
  • Metadata caching with configurable TTL
  • DCR registration (RFC 7591) implemented
  • Gateway OAuth config auto-populated from discovery
  • Admin UI updated with discovery features
  • Credentials stored encrypted
  • Unit tests for all discovery paths
  • Integration tests with major IdPs
  • Documentation updated
  • Code passes make verify
  • PR reviewed and approved

🔗 Related Issues


📓 Additional Context

Existing Codebase Support

The foundation for RFC 8414 discovery already exists in mcpgateway/services/dcr_service.py:

  • discover_as_metadata() method
  • _metadata_cache for caching
  • Configuration via DCR_METADATA_CACHE_TTL

This feature extends the existing implementation for broader gateway integration.

Standards References

Metadata

Metadata

Assignees

No one assigned

    Labels

    SHOULDP2: Important but not vital; high-value items that are not crucial for the immediate releaseenhancementNew feature or requestpythonPython / backend development (FastAPI)securityImproves security

    Type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions