client

package
v0.41.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 22, 2025 License: Apache-2.0 Imports: 18 Imported by: 0

README

OAuth 2.0/2.1 Client for Browser Authentication

This package implements OAuth 2.0/2.1 client functionality for browser-based authentication flows in MCP DevTools. It provides a complete implementation of the authorization code flow with PKCE (Proof Key for Code Exchange) as required by the MCP 2025-06-18 specification.

Overview

The OAuth client enables MCP DevTools to authenticate users via their browser using OAuth 2.0/2.1 authorization servers. This is particularly useful for scenarios where users need to authenticate with identity providers before the MCP server can access protected resources.

Features

  • OAuth 2.1 Compliant: Full implementation of OAuth 2.1 authorization code flow
  • PKCE Support: Implements RFC7636 Proof Key for Code Exchange for enhanced security
  • Browser Integration: Cross-platform browser launching for authentication
  • Localhost Callback Server: Temporary HTTP server for handling OAuth callbacks
  • RFC8414 Discovery: Automatic endpoint discovery from issuer metadata
  • RFC8707 Resource Indicators: Proper token audience binding
  • MCP 2025-06-18 Compliant: Follows latest MCP specification requirements

Architecture

Core Components
  • OAuth2Client: Main interface for OAuth client operations
  • BrowserAuthFlow: High-level authentication flow manager
  • CallbackServer: Localhost HTTP server for OAuth redirects
  • BrowserLauncher: Cross-platform browser opening utility
  • PKCE Utilities: Secure code challenge/verifier generation
Authentication Flow
  1. Configuration: Client is configured with OAuth provider details
  2. Endpoint Discovery: Discovers authorization/token endpoints via RFC8414
  3. PKCE Generation: Creates secure code challenge/verifier pair
  4. Callback Server: Starts temporary localhost HTTP server
  5. Browser Launch: Opens system browser to authorization URL
  6. User Authentication: User completes authentication in browser
  7. Code Exchange: Exchanges authorization code for access token
  8. Cleanup: Shuts down callback server and completes flow

Configuration

Environment Variables
# Enable browser authentication
OAUTH_BROWSER_AUTH=true

# OAuth client configuration
OAUTH_CLIENT_ID="your-client-id"
OAUTH_CLIENT_SECRET="your-client-secret"  # Optional for public clients
OAUTH_ISSUER="https://auth.example.com"
OAUTH_SCOPE="openid profile"
OAUTH_AUDIENCE="https://mcp.example.com"

# Callback server configuration
OAUTH_CALLBACK_PORT=0  # 0 for random port
OAUTH_AUTH_TIMEOUT=5m

# Security settings
OAUTH_REQUIRE_HTTPS=true  # Set false only for development
CLI Flags
./mcp-devtools --transport=http \
    --oauth-browser-auth \
    --oauth-client-id="your-client-id" \
    --oauth-issuer="https://auth.example.com" \
    --oauth-audience="https://mcp.example.com" \
    --oauth-scope="openid profile"

Usage Examples

Basic Browser Authentication
# Enable browser authentication with minimum configuration
OAUTH_BROWSER_AUTH=true \
OAUTH_CLIENT_ID="mcp-devtools-client" \
OAUTH_ISSUER="https://auth.example.com" \
./mcp-devtools --transport=http
With Custom Scopes and Audience
# Request specific scopes and set audience for token binding
OAUTH_BROWSER_AUTH=true \
OAUTH_CLIENT_ID="mcp-devtools-client" \
OAUTH_ISSUER="https://auth.example.com" \
OAUTH_SCOPE="mcp:tools mcp:resources" \
OAUTH_AUDIENCE="https://mcp.example.com" \
./mcp-devtools --transport=http
Development Configuration
# Development setup with HTTP localhost
OAUTH_BROWSER_AUTH=true \
OAUTH_CLIENT_ID="dev-client" \
OAUTH_ISSUER="http://localhost:8080" \
OAUTH_AUDIENCE="http://localhost:18080" \
OAUTH_REQUIRE_HTTPS=false \
./mcp-devtools --transport=http --debug

Security Features

PKCE (Proof Key for Code Exchange)
  • Generates cryptographically secure 256-bit code verifiers
  • Uses SHA256 challenge method for maximum security
  • Prevents authorization code interception attacks
  • Required for all public clients per OAuth 2.1
Token Audience Binding (RFC8707)
  • Explicitly binds tokens to intended resource servers
  • Prevents token reuse across different services
  • Implements resource parameter in authorization/token requests
  • Validates audience claims in received tokens
Secure Callback Handling
  • Uses localhost-only callback URLs for security
  • Implements HTTPS enforcement (configurable for development)
  • Validates state parameters to prevent CSRF attacks
  • Secure token storage and handling

Integration with MCP Server

When browser authentication is enabled, the flow integrates seamlessly with MCP server startup:

  1. Pre-Startup Authentication: Authentication completes before MCP server starts
  2. Token Storage: Access tokens are securely stored for server use
  3. Middleware Integration: Works with existing OAuth resource server middleware
  4. Transport Compatibility: Only available for HTTP transport (not stdio)

Error Handling

The implementation provides comprehensive error handling:

  • Configuration Errors: Invalid or missing configuration parameters
  • Network Errors: Connection failures, timeouts, DNS resolution
  • OAuth Errors: Standard OAuth 2.0 error responses from authorization servers
  • Browser Errors: Browser launching failures, callback timeouts
  • Server Errors: Callback server startup/shutdown issues

Browser Compatibility

Supports cross-platform browser launching:

  • macOS: Uses open command
  • Linux: Uses xdg-open command

Callback Server

The temporary callback server provides:

  • Random Port Selection: Avoids port conflicts
  • Success/Error Pages: User-friendly feedback pages
  • Automatic Shutdown: Cleans up after authentication
  • Security Headers: Appropriate HTTP security headers

Development and Testing

Running Tests
# Run OAuth client tests
go test ./internal/oauth/client/...

# Run with race detection
go test -race ./internal/oauth/client/...
Manual Testing
# Test with debug logging
./mcp-devtools --transport=http \
    --oauth-browser-auth \
    --oauth-client-id="test-client" \
    --oauth-issuer="https://auth.example.com" \
    --debug

Troubleshooting

Common Issues
  1. Browser doesn't open: Check if xdg-open (Linux) or open (macOS) is available
  2. Callback timeout: Increase --oauth-auth-timeout value
  3. Port conflicts: Use --oauth-callback-port=0 for random port
  4. HTTPS errors: Set --oauth-require-https=false for development
Debug Logging

Enable debug logging to see detailed OAuth flow information:

./mcp-devtools --debug --oauth-browser-auth ...

Standards Compliance

This implementation complies with:

  • OAuth 2.1 (draft-ietf-oauth-v2-1-12): Core authorization framework
  • RFC7636: Proof Key for Code Exchange (PKCE)
  • RFC8414: OAuth 2.0 Authorization Server Metadata
  • RFC8707: Resource Indicators for OAuth 2.0
  • MCP 2025-06-18: Model Context Protocol authorization specification

Limitations

  • HTTP Transport Only: Browser authentication requires HTTP transport
  • Desktop/Server Environments: Designed for environments with browser access
  • Single User: Each server instance supports one authenticated user
  • No Token Refresh: Currently implements only initial authentication flow

Future Enhancements

Planned improvements include:

  • Token refresh functionality
  • Multiple user support
  • Enhanced error recovery
  • Additional OAuth flows (device code, etc.)
  • Token persistence across restarts

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func GeneratePKCEChallenge

func GeneratePKCEChallenge() (*types.PKCEChallenge, error)

GeneratePKCEChallenge generates a PKCE code challenge and verifier according to RFC7636

func GenerateState

func GenerateState() (string, error)

GenerateState generates a cryptographically secure state parameter for OAuth flow

func ValidatePKCEChallenge

func ValidatePKCEChallenge(challenge *types.PKCEChallenge, verifier string) error

ValidatePKCEChallenge validates a PKCE challenge against a verifier

Types

type AuthenticationResult

type AuthenticationResult struct {
	Success       bool
	TokenResponse *TokenResponse
	Error         error

	// Additional metadata
	State       string
	ExchangedAt time.Time
}

AuthenticationResult represents the result of browser-based authentication

type AuthenticationSession

type AuthenticationSession struct {
	// PKCE parameters
	PKCEChallenge *types.PKCEChallenge

	// Session state
	State       string
	RedirectURI string

	// Authorization URL
	AuthURL string

	// Callback server
	CallbackServer CallbackServer

	// Result channels
	ResultCh chan *AuthenticationResult
	ErrorCh  chan error

	// Context for cancellation
	Context context.Context
	Cancel  context.CancelFunc
}

AuthenticationSession represents an ongoing OAuth authentication session

type BrowserAuthFlow

type BrowserAuthFlow struct {
	// contains filtered or unexported fields
}

BrowserAuthFlow manages the complete browser-based OAuth authentication flow

func NewBrowserAuthFlow

func NewBrowserAuthFlow(config *OAuth2ClientConfig, logger *logrus.Logger) (*BrowserAuthFlow, error)

NewBrowserAuthFlow creates a new browser authentication flow manager

func (*BrowserAuthFlow) Authenticate

func (f *BrowserAuthFlow) Authenticate(ctx context.Context) (*TokenResponse, error)

Authenticate performs the complete browser-based authentication flow

func (*BrowserAuthFlow) AuthenticateIfRequired

func (f *BrowserAuthFlow) AuthenticateIfRequired(ctx context.Context, required bool) (*TokenResponse, error)

AuthenticateIfRequired performs authentication only if required by configuration

func (*BrowserAuthFlow) AuthenticateWithTimeout

func (f *BrowserAuthFlow) AuthenticateWithTimeout(timeout time.Duration) (*TokenResponse, error)

AuthenticateWithTimeout performs authentication with a custom timeout

func (*BrowserAuthFlow) GetRedirectURI

func (f *BrowserAuthFlow) GetRedirectURI() string

GetRedirectURI returns the redirect URI that would be used for authentication

func (*BrowserAuthFlow) ValidateConfig

func (f *BrowserAuthFlow) ValidateConfig() error

ValidateConfig validates the authentication flow configuration

type BrowserLauncher

type BrowserLauncher interface {
	OpenURL(url string) error
}

BrowserLauncher interface for opening browsers

func NewBrowserLauncher

func NewBrowserLauncher() BrowserLauncher

NewBrowserLauncher creates a new browser launcher

type CallbackServer

type CallbackServer interface {
	Start(ctx context.Context, port int) error
	Stop() error
	GetRedirectURI() string
	GetAuthorizationCode() <-chan string
	GetError() <-chan error
}

CallbackServer interface for handling OAuth callbacks

func NewCallbackServer

func NewCallbackServer(logger *logrus.Logger) CallbackServer

NewCallbackServer creates a new OAuth callback server

type DefaultBrowserLauncher

type DefaultBrowserLauncher struct{}

DefaultBrowserLauncher implements BrowserLauncher for cross-platform browser opening

func (*DefaultBrowserLauncher) OpenURL

func (b *DefaultBrowserLauncher) OpenURL(url string) error

OpenURL opens a URL in the default system browser

type DefaultOAuth2Client

type DefaultOAuth2Client struct {
	// contains filtered or unexported fields
}

DefaultOAuth2Client implements OAuth2Client for browser-based authentication

func (*DefaultOAuth2Client) DiscoverEndpoints

func (c *DefaultOAuth2Client) DiscoverEndpoints(ctx context.Context) error

DiscoverEndpoints discovers OAuth endpoints from the issuer URL using RFC8414 or OpenID Connect Discovery

func (*DefaultOAuth2Client) ExchangeCodeForToken

func (c *DefaultOAuth2Client) ExchangeCodeForToken(ctx context.Context, code string, pkce *types.PKCEChallenge, redirectURI string) (*TokenResponse, error)

ExchangeCodeForToken exchanges an authorization code for an access token

func (*DefaultOAuth2Client) StartAuthentication

func (c *DefaultOAuth2Client) StartAuthentication(ctx context.Context) (*AuthenticationSession, error)

StartAuthentication initiates the OAuth 2.0 authorization code flow with PKCE

func (*DefaultOAuth2Client) ValidateConfiguration

func (c *DefaultOAuth2Client) ValidateConfiguration() error

ValidateConfiguration validates the OAuth client configuration

type LocalCallbackServer

type LocalCallbackServer struct {
	// contains filtered or unexported fields
}

LocalCallbackServer implements CallbackServer for localhost OAuth redirects

func (*LocalCallbackServer) GetAuthorizationCode

func (s *LocalCallbackServer) GetAuthorizationCode() <-chan string

GetAuthorizationCode returns a channel that receives the authorization code

func (*LocalCallbackServer) GetError

func (s *LocalCallbackServer) GetError() <-chan error

GetError returns a channel that receives errors

func (*LocalCallbackServer) GetRedirectURI

func (s *LocalCallbackServer) GetRedirectURI() string

GetRedirectURI returns the redirect URI for this callback server

func (*LocalCallbackServer) Start

func (s *LocalCallbackServer) Start(ctx context.Context, port int) error

Start starts the callback server on the specified port (0 for random)

func (*LocalCallbackServer) Stop

func (s *LocalCallbackServer) Stop() error

Stop stops the callback server

type OAuth2Client

type OAuth2Client interface {
	// StartAuthentication initiates the OAuth 2.0 authorization code flow
	StartAuthentication(ctx context.Context) (*AuthenticationSession, error)

	// ExchangeCodeForToken exchanges authorization code for access token
	ExchangeCodeForToken(ctx context.Context, code string, pkce *types.PKCEChallenge, redirectURI string) (*TokenResponse, error)

	// DiscoverEndpoints discovers OAuth endpoints from issuer URL
	DiscoverEndpoints(ctx context.Context) error

	// ValidateConfiguration validates the client configuration
	ValidateConfiguration() error
}

OAuth2Client interface for browser-based OAuth flows

func NewOAuth2Client

func NewOAuth2Client(config *OAuth2ClientConfig, logger *logrus.Logger) (OAuth2Client, error)

NewOAuth2Client creates a new OAuth 2.0 client for browser authentication

type OAuth2ClientConfig

type OAuth2ClientConfig struct {
	// Client credentials
	ClientID     string `json:"client_id"`
	ClientSecret string `json:"client_secret,omitempty"` // Optional for public clients

	// Authorization server endpoints
	AuthorizationEndpoint string `json:"authorization_endpoint"`
	TokenEndpoint         string `json:"token_endpoint"`

	// Optional discovery
	IssuerURL string `json:"issuer_url,omitempty"` // For .well-known/oauth-authorization-server discovery

	// Redirect configuration
	RedirectURI string `json:"redirect_uri"` // Usually http://localhost:PORT/callback

	// OAuth parameters
	Scope    string `json:"scope,omitempty"`    // Requested scopes
	Resource string `json:"resource,omitempty"` // RFC8707 resource parameter

	// Security settings
	RequireHTTPS bool `json:"require_https"` // Default true, false only for localhost

	// Timeouts
	AuthTimeout time.Duration `json:"auth_timeout"` // How long to wait for user authentication
	ServerPort  int           `json:"server_port"`  // Port for callback server (0 = random)
}

OAuth2ClientConfig represents OAuth 2.0 client configuration for browser authentication

type TokenResponse

type TokenResponse struct {
	AccessToken  string `json:"access_token"`
	TokenType    string `json:"token_type"`
	ExpiresIn    int64  `json:"expires_in,omitempty"`
	RefreshToken string `json:"refresh_token,omitempty"`
	Scope        string `json:"scope,omitempty"`
}

TokenResponse represents an OAuth 2.0 token response

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL