rust_mcp_sdk/auth/
auth_info.rs1#[cfg(feature = "auth")]
2use crate::auth::{AuthClaims, AuthenticationError, IntrospectionResponse};
3use crate::{auth::Audience, utils::unix_timestamp_to_systemtime};
4#[cfg(feature = "auth")]
5use jsonwebtoken::TokenData;
6use serde::{Deserialize, Serialize};
7use serde_json::Map;
8use std::time::SystemTime;
9
10#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct AuthInfo {
13 pub token_unique_id: String,
16
17 #[serde(skip_serializing_if = "std::option::Option::is_none")]
19 pub client_id: Option<String>,
20
21 #[serde(skip_serializing_if = "std::option::Option::is_none")]
23 pub user_id: Option<String>,
24
25 #[serde(skip_serializing_if = "std::option::Option::is_none")]
27 pub scopes: Option<Vec<String>>,
28
29 #[serde(skip_serializing_if = "std::option::Option::is_none")]
32 pub expires_at: Option<SystemTime>,
33
34 #[serde(skip_serializing_if = "std::option::Option::is_none")]
37 pub audience: Option<Audience>,
38
39 #[serde(flatten, skip_serializing_if = "std::option::Option::is_none")]
42 pub extra: Option<Map<String, serde_json::Value>>,
43}
44
45#[cfg(feature = "auth")]
46impl AuthInfo {
47 pub fn from_token_data(
48 token: String,
49 token_data: TokenData<AuthClaims>,
50 extra: Option<Map<String, serde_json::Value>>,
51 ) -> Result<Self, AuthenticationError> {
52 let client_id = token_data.claims.authorized_party.or(token_data
53 .claims
54 .client_id
55 .or(token_data.claims.application_id));
56
57 let scopes = token_data
58 .claims
59 .scope
60 .map(|c| c.split(" ").map(|s| s.to_string()).collect::<Vec<_>>());
61
62 let expires_at = token_data
63 .claims
64 .expiration
65 .map(|v| unix_timestamp_to_systemtime(v as u64));
66
67 let token_unique_id = token_data.claims.jwt_id.unwrap_or(token);
68
69 Ok(AuthInfo {
70 token_unique_id,
71 client_id,
72 scopes,
73 user_id: token_data.claims.subject,
74 expires_at,
75 audience: token_data.claims.audience,
76 extra,
77 })
78 }
79
80 pub fn from_introspection_response(
81 token: String,
82 data: IntrospectionResponse,
83 extra: Option<Map<String, serde_json::Value>>,
84 ) -> Result<Self, AuthenticationError> {
85 let scopes = data
86 .scope
87 .map(|c| c.split(" ").map(|s| s.to_string()).collect::<Vec<_>>());
88
89 let expires_at = data
90 .expiration
91 .map(|v| unix_timestamp_to_systemtime(v as u64));
92
93 let token_unique_id = data.jwt_id.unwrap_or(token);
94
95 Ok(AuthInfo {
96 token_unique_id,
97 client_id: data.client_id,
98 user_id: data.subject,
99 scopes,
100 expires_at,
101 audience: data.audience,
102 extra,
103 })
104 }
105}