turbomcp_auth/
types.rs

1//! Core Authentication Types
2//!
3//! This module contains core types used throughout the TurboMCP authentication system.
4
5use std::collections::HashMap;
6use std::time::SystemTime;
7
8use async_trait::async_trait;
9use oauth2::RefreshToken;
10use serde::{Deserialize, Serialize};
11
12use turbomcp_protocol::{Error as McpError, Result as McpResult};
13
14use super::config::AuthProviderType;
15
16/// Authentication context containing user information and session data
17#[derive(Debug, Clone, Serialize, Deserialize)]
18pub struct AuthContext {
19    /// User ID
20    pub user_id: String,
21    /// User information
22    pub user: UserInfo,
23    /// User roles
24    pub roles: Vec<String>,
25    /// User permissions
26    pub permissions: Vec<String>,
27    /// Session ID
28    pub session_id: String,
29    /// Token information
30    pub token: Option<TokenInfo>,
31    /// Authentication provider used
32    pub provider: String,
33    /// Authentication timestamp
34    pub authenticated_at: SystemTime,
35    /// Token expiry time
36    pub expires_at: Option<SystemTime>,
37    /// Additional metadata
38    pub metadata: HashMap<String, serde_json::Value>,
39}
40
41/// User information
42#[derive(Debug, Clone, Serialize, Deserialize)]
43pub struct UserInfo {
44    /// User ID
45    pub id: String,
46    /// Username
47    pub username: String,
48    /// Email address
49    pub email: Option<String>,
50    /// Display name
51    pub display_name: Option<String>,
52    /// Avatar URL
53    pub avatar_url: Option<String>,
54    /// User metadata
55    pub metadata: HashMap<String, serde_json::Value>,
56}
57
58/// Token information
59#[derive(Debug, Clone, Serialize, Deserialize)]
60pub struct TokenInfo {
61    /// Access token
62    pub access_token: String,
63    /// Token type (Bearer, etc.)
64    pub token_type: String,
65    /// Refresh token
66    pub refresh_token: Option<String>,
67    /// Token expiry in seconds
68    pub expires_in: Option<u64>,
69    /// Token scope
70    pub scope: Option<String>,
71}
72
73/// Authentication provider trait
74#[async_trait]
75pub trait AuthProvider: Send + Sync + std::fmt::Debug {
76    /// Provider name
77    fn name(&self) -> &str;
78
79    /// Provider type
80    fn provider_type(&self) -> AuthProviderType;
81
82    /// Authenticate user with credentials
83    async fn authenticate(&self, credentials: AuthCredentials) -> McpResult<AuthContext>;
84
85    /// Validate existing token/session
86    async fn validate_token(&self, token: &str) -> McpResult<AuthContext>;
87
88    /// Refresh access token
89    async fn refresh_token(&self, refresh_token: &str) -> McpResult<TokenInfo>;
90
91    /// Revoke token/session
92    async fn revoke_token(&self, token: &str) -> McpResult<()>;
93
94    /// Get user information
95    async fn get_user_info(&self, token: &str) -> McpResult<UserInfo>;
96}
97
98/// Authentication credentials
99#[derive(Debug, Clone, Serialize, Deserialize)]
100pub enum AuthCredentials {
101    /// Username and password
102    UsernamePassword {
103        /// Username
104        username: String,
105        /// Password
106        password: String,
107    },
108    /// API key
109    ApiKey {
110        /// API key
111        key: String,
112    },
113    /// OAuth 2.0 authorization code
114    OAuth2Code {
115        /// Authorization code
116        code: String,
117        /// State parameter
118        state: String,
119    },
120    /// JWT token
121    JwtToken {
122        /// JWT token
123        token: String,
124    },
125    /// Custom credentials
126    Custom {
127        /// Custom credential data
128        data: HashMap<String, serde_json::Value>,
129    },
130}
131
132/// Secure token storage abstraction
133#[async_trait]
134pub trait TokenStorage: Send + Sync + std::fmt::Debug {
135    /// Store access token securely
136    async fn store_access_token(&self, user_id: &str, token: &AccessToken) -> McpResult<()>;
137
138    /// Retrieve access token
139    async fn get_access_token(&self, user_id: &str) -> McpResult<Option<AccessToken>>;
140
141    /// Store refresh token securely (encrypted at rest)
142    async fn store_refresh_token(&self, user_id: &str, token: &RefreshToken) -> McpResult<()>;
143
144    /// Retrieve refresh token
145    async fn get_refresh_token(&self, user_id: &str) -> McpResult<Option<RefreshToken>>;
146
147    /// Remove all tokens for user (logout)
148    async fn revoke_tokens(&self, user_id: &str) -> McpResult<()>;
149
150    /// List all users with stored tokens (for admin)
151    async fn list_users(&self) -> McpResult<Vec<String>>;
152}
153
154/// Secure access token with metadata
155#[derive(Debug, Clone)]
156pub struct AccessToken {
157    /// The actual token
158    pub(crate) token: String,
159    /// Token expiration time
160    pub(crate) expires_at: Option<SystemTime>,
161    /// Token scopes
162    pub(crate) scopes: Vec<String>,
163    /// Provider metadata
164    pub(crate) metadata: HashMap<String, serde_json::Value>,
165}
166
167impl AccessToken {
168    /// Create a new access token
169    pub fn new(
170        token: String,
171        expires_at: Option<SystemTime>,
172        scopes: Vec<String>,
173        metadata: HashMap<String, serde_json::Value>,
174    ) -> Self {
175        Self {
176            token,
177            expires_at,
178            scopes,
179            metadata,
180        }
181    }
182
183    /// Get the token value
184    pub fn token(&self) -> &str {
185        &self.token
186    }
187
188    /// Get the token expiration time
189    pub fn expires_at(&self) -> Option<SystemTime> {
190        self.expires_at
191    }
192
193    /// Get the token scopes
194    pub fn scopes(&self) -> &[String] {
195        &self.scopes
196    }
197
198    /// Get the token metadata
199    pub fn metadata(&self) -> &HashMap<String, serde_json::Value> {
200        &self.metadata
201    }
202}
203
204/// Authentication middleware trait
205#[async_trait]
206pub trait AuthMiddleware: Send + Sync {
207    /// Extract authentication token from request
208    async fn extract_token(&self, headers: &HashMap<String, String>) -> Option<String>;
209
210    /// Handle authentication failure
211    async fn handle_auth_failure(&self, error: McpError) -> McpResult<()>;
212}
213
214/// Default authentication middleware
215#[derive(Debug, Clone)]
216pub struct DefaultAuthMiddleware;
217
218#[async_trait]
219impl AuthMiddleware for DefaultAuthMiddleware {
220    async fn extract_token(&self, headers: &HashMap<String, String>) -> Option<String> {
221        // Try Authorization header first
222        if let Some(auth_header) = headers
223            .get("authorization")
224            .or_else(|| headers.get("Authorization"))
225        {
226            if let Some(token) = auth_header.strip_prefix("Bearer ") {
227                return Some(token.to_string());
228            }
229            if let Some(token) = auth_header.strip_prefix("ApiKey ") {
230                return Some(token.to_string());
231            }
232        }
233
234        // Try X-API-Key header
235        if let Some(api_key) = headers
236            .get("x-api-key")
237            .or_else(|| headers.get("X-API-Key"))
238        {
239            return Some(api_key.clone());
240        }
241
242        None
243    }
244
245    async fn handle_auth_failure(&self, error: McpError) -> McpResult<()> {
246        tracing::warn!("Authentication failed: {}", error);
247        Err(Box::new(error))
248    }
249}