* fix(docs): Add -p mcp-client-examples to cargo run commands in clients/README.md * fix(docs): Add -p mcp-server-examples to cargo run commands in examples/servers/README.md * fix(docs): Add -p parameter to cargo run commands in other documentation
4.5 KiB
4.5 KiB
Model Context Protocol OAuth Authorization
This document describes the OAuth 2.1 authorization implementation for Model Context Protocol (MCP), following the MCP 2025-03-26 Authorization Specification.
Features
- Full support for OAuth 2.1 authorization flow
- PKCE support for enhanced security
- Authorization server metadata discovery
- Dynamic client registration
- Automatic token refresh
- Authorized HTTP Client implementation
Usage Guide
1. Enable Features
Enable the auth feature in Cargo.toml:
[dependencies]
rmcp = { version = "0.1", features = ["auth", "transport-streamable-http-client-reqwest"] }
2. Use OAuthState
// Initialize oauth state machine
let mut oauth_state = OAuthState::new(&server_url, None)
.await
.context("Failed to initialize oauth state machine")?;
oauth_state
.start_authorization(&["mcp", "profile", "email"], MCP_REDIRECT_URI)
.await
.context("Failed to start authorization")?;
3. Get authorization url and do callback
// Get authorization URL and guide user to open it
let auth_url = oauth_state.get_authorization_url().await?;
println!("Please open the following URL in your browser for authorization:\n{}", auth_url);
// Handle callback - In real applications, this is typically done in a callback server
let auth_code = "Authorization code (`code` param) obtained from browser after user authorization";
let csrf_token = "CSRF token (`state` param) obtained from browser after user authorization";
let credentials = oauth_state.handle_callback(auth_code, csrf_token).await?;
println!("Authorization successful, access token: {}", credentials.access_token);
4. Use Authorized Streamable HTTP Transport and create client
let am = oauth_state
.into_authorization_manager()
.ok_or_else(|| anyhow::anyhow!("Failed to get authorization manager"))?;
let client = AuthClient::new(reqwest::Client::default(), am);
let transport = StreamableHttpClientTransport::with_client(
client,
StreamableHttpClientTransportConfig::with_uri(MCP_SERVER_URL),
);
// Create client and connect to MCP server
let client_service = ClientInfo::default();
let client = client_service.serve(transport).await?;
5. Use Authorized HTTP Client after authorized
let client = oauth_state.to_authorized_http_client().await?;
Complete Examples
- Client:
examples/clients/src/auth/oauth_client.rs - Server:
examples/servers/src/complex_auth_streamhttp.rs
Running the Examples
# Run the OAuth server
cargo run -p mcp-server-examples --example servers_complex_auth_streamhttp
# Run the OAuth client (in another terminal)
cargo run -p mcp-client-examples --example clients_oauth_client
Authorization Flow Description
- Metadata Discovery: Client attempts to get authorization server metadata from
/.well-known/oauth-authorization-server - Client Registration: If supported, client dynamically registers itself
- Authorization Request: Build authorization URL with PKCE and guide user to access
- Authorization Code Exchange: After user authorization, exchange authorization code for access token
- Token Usage: Use access token for API calls
- Token Refresh: Automatically use refresh token to get new access token when current one expires
Security Considerations
- All tokens are securely stored in memory
- PKCE implementation prevents authorization code interception attacks
- Automatic token refresh support reduces user intervention
- Only accepts HTTPS connections or secure local callback URIs
Troubleshooting
If you encounter authorization issues, check the following:
- Ensure server supports OAuth 2.1 authorization
- Verify callback URI matches server's allowed redirect URIs
- Check network connection and firewall settings
- Verify server supports metadata discovery or dynamic client registration