29 releases (stable)
Uses new Rust 2024
| new 3.0.0-exp.2 | Jan 13, 2026 |
|---|---|
| 3.0.0-exp | Jan 12, 2026 |
| 2.3.6 | Jan 3, 2026 |
| 2.3.5 | Dec 21, 2025 |
| 2.0.5 | Oct 24, 2025 |
#493 in Authentication
Used in 4 crates
1.5MB
24K
SLoC
TurboMCP Auth
OAuth 2.1 and authentication for TurboMCP with MCP protocol compliance.
Features
- OAuth 2.1 Flows - RFC 8707/9728/7591 compliant with PKCE support
- Authorization Code flow (with PKCE for public/confidential clients)
- Client Credentials flow (server-to-server)
- Token refresh and validation
- Multi-Provider Support - Google, GitHub, Microsoft, GitLab, Apple, Okta, Auth0, Keycloak (with provider-specific OAuth 2.1 configurations)
- OAuth2Provider - Full AuthProvider implementation for OAuth 2.1
- API Key Authentication - Simple API key-based authentication
- Server-Side Helpers - RFC 9728 Protected Resource Metadata and WWW-Authenticate headers
- Session Management - Secure token management with configurable storage
- DPoP Support - Optional RFC 9449 proof-of-possession tokens
- Comprehensive Validation - RFC 8707 canonical URI validation, token format validation
Quick Start
Client: OAuth 2.1 Authorization Code Flow
use turbomcp_auth::{
oauth2::OAuth2Client,
config::{OAuth2Config, OAuth2FlowType, ProviderType},
};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create OAuth2 configuration
let config = OAuth2Config {
client_id: "my-client-id".to_string(),
client_secret: "my-client-secret".to_string(),
auth_url: "https://provider.example.com/oauth/authorize".to_string(),
token_url: "https://provider.example.com/oauth/token".to_string(),
redirect_uri: "http://localhost:8080/callback".to_string(),
scopes: vec!["openid".to_string(), "profile".to_string()],
flow_type: OAuth2FlowType::AuthorizationCode,
additional_params: Default::default(),
security_level: Default::default(),
#[cfg(feature = "dpop")]
dpop_config: None,
mcp_resource_uri: None,
auto_resource_indicators: true,
};
// Create OAuth2 client
let client = OAuth2Client::new(&config, ProviderType::Generic)?;
// Step 1: Generate authorization URL with PKCE
let state = uuid::Uuid::new_v4().to_string();
let (auth_url, code_verifier) = client.authorization_code_flow(config.scopes, state);
println!("1. Open authorization URL in browser:\n{}\n", auth_url);
// Step 2: User authorizes, redirect comes with code
// After user authorizes and redirects with code...
// Step 3: Exchange code for token
let token = client.exchange_code_for_token("auth_code".to_string(), code_verifier).await?;
println!("Access token: {}", token.access_token);
// Step 4: Use token to access protected resources
// Authorization: Bearer {token.access_token}
// Step 5: Refresh token when expired
if let Some(refresh_token) = &token.refresh_token {
let new_token = client.refresh_access_token(refresh_token).await?;
println!("Refreshed token: {}", new_token.access_token);
}
Ok(())
}
Server: Protected Resource with RFC 9728 Metadata
use turbomcp_auth::server::{
ProtectedResourceMetadataBuilder, WwwAuthenticateBuilder, BearerTokenValidator,
};
// Serve Protected Resource Metadata at /.well-known/protected-resource
fn get_metadata() -> Result<String, Box<dyn std::error::Error>> {
let metadata = ProtectedResourceMetadataBuilder::new(
"https://mcp.example.com".to_string(),
"https://auth.example.com/.well-known/oauth-authorization-server".to_string(),
)
.with_scopes(vec!["mcp:read".to_string(), "mcp:write".to_string()])
.with_documentation("https://mcp.example.com/docs".to_string())
.build();
Ok(serde_json::to_string_pretty(&metadata)?)
}
// Handle 401 Unauthorized responses
fn handle_unauthorized() -> (String, String) {
let www_auth = WwwAuthenticateBuilder::new(
"https://mcp.example.com/.well-known/protected-resource".to_string(),
)
.with_scope("mcp:read".to_string())
.build();
(www_auth, "Unauthorized".to_string())
}
// Validate incoming bearer tokens
fn extract_token(auth_header: &str) -> Result<String, Box<dyn std::error::Error>> {
let token = BearerTokenValidator::extract_from_header(auth_header)?;
BearerTokenValidator::validate_format(&token)?;
Ok(token)
}
Usage
[dependencies]
turbomcp-auth = "3.0.0-exp"
# With DPoP support for enhanced security
turbomcp-auth = { version = "3.0.0-exp", features = ["dpop"] }
# With tokio runtime
tokio = { version = "1", features = ["full"] }
uuid = { version = "1", features = ["v4"] }
Feature Flags
default- Core authentication (no optional features)dpop- Enable DPoP (RFC 9449) token binding support viaturbomcp-dpop
Supported Providers
TurboMCP Auth supports all major OAuth 2.1 providers with pre-configured endpoints and scopes:
| Provider | Type | Scopes | Support | Notes |
|---|---|---|---|---|
| Social | openid, email, profile |
✅ Full OAuth 2.1 | PKCE required | |
| GitHub | Social | user:email, read:user |
✅ Full OAuth 2.1 | Token refresh via offline_access |
| Microsoft | Enterprise | openid, profile, email, User.Read |
✅ Full OAuth 2.1 | Azure AD integrated |
| GitLab | Self-Hosted | read_user, openid |
✅ Full OAuth 2.1 | Self-hosted compatible |
| Apple | Identity | openid, email, name |
✅ Full OAuth 2.1 | Requires response_mode=form_post |
| Okta | Enterprise | openid, email, profile |
✅ Full OAuth 2.1 | Enterprise SSO ready |
| Auth0 | Identity Platform | openid, email, profile |
✅ Full OAuth 2.1 | Unified identity management |
| Keycloak | Open Source OIDC | openid, email, profile |
✅ Full OAuth 2.1 | Self-hosted OIDC provider |
| Generic | Custom | Configurable | ✅ Full OAuth 2.1 | Any OIDC-compliant provider |
All providers support:
- ✅ PKCE (RFC 7636) - Automatic proof key generation
- ✅ Token refresh - Automatic and manual refresh
- ✅ Resource Indicators (RFC 8707) - MCP server binding
- ✅ Protected Resource Metadata (RFC 9728) - Server-side discovery
- ✅ DPoP optional (RFC 9449) - Token binding for enhanced security
Provider Examples
Google Sign-In
let client = OAuth2Client::new(&config, ProviderType::Google)?;
Microsoft Azure AD
let client = OAuth2Client::new(&config, ProviderType::Microsoft)?;
Apple Sign In
let client = OAuth2Client::new(&config, ProviderType::Apple)?;
// Note: Apple requires PKCE and response_mode=form_post
Okta Enterprise
let client = OAuth2Client::new(&config, ProviderType::Okta)?;
// Replace {domain} in auth/token URLs with your Okta domain
Auth0
let client = OAuth2Client::new(&config, ProviderType::Auth0)?;
// Configure with your Auth0 tenant domain
Keycloak Self-Hosted
let client = OAuth2Client::new(&config, ProviderType::Keycloak)?;
// Configure with your Keycloak realm and server URL
Custom Provider
let client = OAuth2Client::new(&config, ProviderType::Generic)?;
// Or use ProviderType::Custom("my-provider".to_string())
Architecture
Core Components
-
OAuth2Client (
oauth2::OAuth2Client)- Authorization Code flow with PKCE (RFC 7636)
- Client Credentials flow (server-to-server)
- Token refresh and validation
- Provider-specific configurations for:
- Social Login: Google, GitHub
- Enterprise: Microsoft, Okta, Keycloak
- Identity Platforms: Apple, Auth0
- Custom: Generic provider with configurable endpoints
-
OAuth2Provider (
providers::OAuth2Provider)- Implements AuthProvider trait
- Token validation via userinfo endpoint
- Token caching and refresh management
- Integration with authentication manager
-
AuthManager (
manager::AuthManager)- Coordinates multiple authentication providers
- Stateless authentication (MCP compliant)
- Token validation on every request
-
Server Helpers (
server::*)ProtectedResourceMetadataBuilder- RFC 9728 metadata generationWwwAuthenticateBuilder- RFC 9728 401 response headersBearerTokenValidator- Token extraction and validation
RFC Compliance
- RFC 7636 - PKCE (Proof Key for Public OAuth Clients)
- RFC 7591 - Dynamic Client Registration Protocol
- RFC 8707 - Resource Indicators for OAuth 2.0
- RFC 9728 - OAuth 2.0 Protected Resource Metadata
- RFC 9449 - DPoP (optional, via
turbomcp-dpop)
Examples
Run the examples to see the implementations in action:
# OAuth 2.1 Authorization Code Flow
cargo run --example oauth2_auth_code_flow
# Protected Resource Server with RFC 9728
cargo run --example protected_resource_server
Security Best Practices
- Use HTTPS - Always use HTTPS for redirect URIs and token endpoints
- PKCE - Automatically enabled for Authorization Code flow (RFC 7636)
- Token Storage - Tokens are never logged or serialized unnecessarily
- Constant-Time Comparison - Token validation uses constant-time comparison
- DPoP - Enable DPoP feature for enhanced security (RFC 9449)
- Scope Validation - Always validate token scopes server-side
- Short Expiration - Use short-lived access tokens with refresh tokens
Testing
cargo test --lib --package turbomcp-auth
cargo test --lib --package turbomcp-dpop # If dpop feature enabled
License
MIT
Dependencies
~101MB
~2M SLoC