Skip to content

๐Ÿ” Implement OAuth 2.1 Compliance for 2025 MCP Security Standardsย #52

@avrabe

Description

@avrabe

๐Ÿ” Implement OAuth 2.1 Compliance for 2025 MCP Security Standards

Problem Statement

The current authentication system uses custom API keys instead of the official 2025 MCP security standards:

Current Issues:

  • Custom API key system (not standards-compliant)
  • Static token-based authentication
  • No OAuth 2.1 support as required by MCP 2025 specification
  • Token passthrough vulnerabilities possible
  • Non-compliant with latest MCP security guidelines

Standards Gap:

  • MCP 2025 mandates OAuth 2.1 for secure authorization
  • PKCE (Proof Key for Code Exchange) is required for all clients
  • Dynamic token validation with proper audience verification
  • Modern security capabilities from OAuth 2.1 ecosystem

Motivation

Official MCP 2025 Requirements

From MCP Security Research:

"In March 2025, the MCP specification took a major leap forward with the release of a new specification that standardizes Authorization using OAuth 2.1"

Key Requirements:

  • OAuth 2.1 compliance is mandatory for production deployments
  • PKCE support raises security baseline significantly
  • Token audience validation prevents unauthorized usage
  • Identity provider integration for enterprise deployments

Security Benefits

  • Eliminate token passthrough vulnerabilities
  • Dynamic token validation vs static API keys
  • Enterprise identity provider integration (Azure AD, Okta, Keycloak)
  • MFA support through identity providers
  • Audit compliance with standard protocols

Competitive Requirements

  • Official MCP servers will require OAuth 2.1 compliance
  • Enterprise adoption blocked without standards compliance
  • Framework credibility depends on following official specifications

Solution Design

1. OAuth 2.1 Core Implementation

pub struct OAuth21Config {
    pub client_id: String,
    pub client_secret: Option<String>,  // Optional for PKCE
    pub authorization_server: String,
    pub token_endpoint: String, 
    pub jwks_uri: String,
    pub audience: String,
    pub scopes: Vec<String>,
    pub pkce_required: bool,
}

pub struct OAuth21Middleware {
    config: OAuth21Config,
    jwks_client: JwksClient,
    token_validator: TokenValidator,
}

2. PKCE Implementation

#[derive(Debug, Clone)]
pub struct PkceChallenge {
    pub code_verifier: String,
    pub code_challenge: String,
    pub code_challenge_method: String,  // S256
}

impl PkceChallenge {
    pub fn new() -> Self {
        let code_verifier = generate_secure_random(128);  
        let code_challenge = base64_url_encode(sha256(code_verifier.as_bytes()));
        
        Self {
            code_verifier,
            code_challenge,
            code_challenge_method: "S256".to_string(),
        }
    }
}

3. Token Validation

#[async_trait]
impl AuthenticationMiddleware for OAuth21Middleware {
    async fn authenticate(&self, request: &Request) -> Result<AuthContext, AuthError> {
        // Extract Bearer token
        let token = self.extract_bearer_token(request)?;
        
        // Validate token with JWKS
        let claims = self.token_validator.validate_token(&token).await?;
        
        // Verify audience (critical for MCP compliance)
        if !claims.audience.contains(&self.config.audience) {
            return Err(AuthError::InvalidAudience);
        }
        
        // Verify issuer
        if claims.issuer != self.config.authorization_server {
            return Err(AuthError::InvalidIssuer);
        }
        
        // Create auth context
        Ok(AuthContext {
            user_id: claims.subject,
            scopes: claims.scopes,
            token_claims: claims,
            authenticated_at: Utc::now(),
        })
    }
}

4. Identity Provider Integration

pub enum IdentityProvider {
    Keycloak(KeycloakConfig),
    AzureAD(AzureADConfig), 
    Okta(OktaConfig),
    Custom(CustomOAuth21Config),
}

impl IdentityProvider {
    pub async fn discover_endpoints(&self) -> Result<OAuth21Config, DiscoveryError> {
        match self {
            IdentityProvider::Keycloak(config) => {
                let discovery_url = format!("{}/auth/realms/{}/.well-known/openid_configuration", 
                    config.base_url, config.realm);
                self.fetch_discovery(&discovery_url).await
            }
            IdentityProvider::AzureAD(config) => {
                let discovery_url = format!("https://login.microsoftonline.com/{}/v2.0/.well-known/openid_configuration",
                    config.tenant_id);
                self.fetch_discovery(&discovery_url).await
            }
            // ... other providers
        }
    }
}

5. Device Flow Support (Local Development)

// For stdio transport and local development
pub struct DeviceFlowAuth {
    config: OAuth21Config,
}

impl DeviceFlowAuth {
    pub async fn start_device_flow(&self) -> Result<DeviceFlowResponse, AuthError> {
        let response: DeviceFlowResponse = self.client
            .post(&format!("{}/device", self.config.token_endpoint))
            .form(&[
                ("client_id", &self.config.client_id),
                ("scope", &self.config.scopes.join(" ")),
            ])
            .send()
            .await?
            .json()
            .await?;
            
        println!("Visit: {} and enter code: {}", 
            response.verification_uri, 
            response.user_code);
            
        Ok(response)
    }
}

Implementation Plan

Phase 1: OAuth 2.1 Core (Week 1)

  • Create pulseengine-mcp-oauth21 crate
  • Implement JWT token validation with JWKS
  • Add PKCE challenge/verify logic
  • Create basic OAuth 2.1 middleware
  • Add comprehensive error handling

Phase 2: Identity Provider Integration (Week 2)

  • Implement Keycloak integration with discovery
  • Add Azure AD support for enterprise
  • Create Okta integration
  • Add generic OpenID Connect provider support
  • Implement endpoint discovery automation

Phase 3: Device Flow & Development (Week 3)

  • Implement OAuth 2.1 device flow for local development
  • Add stdio transport authentication
  • Create development-friendly configuration
  • Add token caching and refresh logic
  • Implement graceful degradation for development

Phase 4: Production Integration (Week 4)

  • Integrate with existing security middleware
  • Add migration path from API key system
  • Create configuration examples for common scenarios
  • Add comprehensive testing and security audit
  • Create deployment documentation

Configuration Examples

Environment-Based Setup

# OAuth 2.1 Configuration
MCP_OAUTH21_CLIENT_ID=mcp-server-client
MCP_OAUTH21_CLIENT_SECRET=your-secret-here
MCP_OAUTH21_ISSUER=https://auth.mycompany.com
MCP_OAUTH21_AUDIENCE=mcp://my-server
MCP_OAUTH21_SCOPES=mcp:read,mcp:write

# Identity Provider (Auto-discovery)
MCP_IDENTITY_PROVIDER=keycloak
MCP_KEYCLOAK_BASE_URL=https://auth.mycompany.com
MCP_KEYCLOAK_REALM=mcp-realm

# Development Mode (Device Flow)
MCP_DEV_MODE=true  # Enables device flow for local development

Programmatic Configuration

use pulseengine_mcp_oauth21::*;

#[mcp_server(
    name = "OAuth21 Server",
    auth_provider = "oauth21"
)]
struct OAuth21Server;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let oauth_config = OAuth21Config {
        client_id: env::var("MCP_OAUTH21_CLIENT_ID")?,
        client_secret: env::var("MCP_OAUTH21_CLIENT_SECRET").ok(),
        authorization_server: env::var("MCP_OAUTH21_ISSUER")?,
        audience: env::var("MCP_OAUTH21_AUDIENCE")?,
        scopes: vec!["mcp:read".to_string(), "mcp:write".to_string()],
        pkce_required: true,
    };
    
    let mut server = OAuth21Server::with_oauth21(oauth_config).await?;
    server.run().await?;
    Ok(())
}

Enterprise Keycloak Example

let identity_provider = IdentityProvider::Keycloak(KeycloakConfig {
    base_url: "https://auth.enterprise.com".to_string(),
    realm: "mcp-production".to_string(),
    client_id: "mcp-server".to_string(),
});

let oauth_config = identity_provider.discover_endpoints().await?;
let server = McpServer::with_oauth21(oauth_config).await?;

Acceptance Criteria

Standards Compliance

  • Full OAuth 2.1 specification compliance
  • PKCE implementation passes RFC 7636 tests
  • JWT validation follows RFC 7519 standards
  • Token audience validation per MCP 2025 requirements
  • OpenID Connect discovery protocol support

Security Requirements

  • No token passthrough vulnerabilities
  • Secure random generation for PKCE challenges
  • Proper JWT signature validation with JWKS
  • Token expiration and refresh handling
  • Secure credential storage and handling

Integration Requirements

  • Works with major identity providers (Keycloak, Azure AD, Okta)
  • Backward compatibility with existing API key system
  • Device flow support for local development
  • Environment variable configuration
  • Migration tooling from current system

Developer Experience

  • Auto-discovery of identity provider endpoints
  • Clear error messages for configuration issues
  • Simple development setup with device flow
  • Comprehensive examples and documentation
  • Testing utilities for OAuth 2.1 scenarios

Migration Strategy

Phase 1: Parallel Support

  • Keep existing API key system functional
  • Add OAuth 2.1 as optional authentication method
  • Allow hybrid configuration (API keys + OAuth 2.1)

Phase 2: Migration Tooling

// Migration helper
pub struct AuthMigrationTool {
    current_config: ApiKeyConfig,
    target_config: OAuth21Config,
}

impl AuthMigrationTool {
    pub async fn migrate_to_oauth21(&self) -> Result<(), MigrationError> {
        // Guided migration process
    }
}

Phase 3: Deprecation Path

  • Mark API key system as deprecated
  • Provide migration timeline (6 months)
  • Maintain backward compatibility during transition

References & Research

Official MCP Standards

Technical Specifications

Industry Implementation Examples

Success Metrics

  1. Compliance: 100% OAuth 2.1 specification compliance
  2. Security: Passes automated security scanning
  3. Performance: <5ms authentication overhead
  4. Adoption: 90% of new deployments use OAuth 2.1
  5. Enterprise: Integration with 3+ identity providers

This brings the framework into full compliance with 2025 MCP security standards and enables enterprise adoption with proper identity management integration.

Priority: High - Required for standards compliance and enterprise adoption
Effort: High - Comprehensive OAuth 2.1 implementation
Impact: High - Enables enterprise deployments and future-proofs security

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions