rust_mcp_sdk/auth/spec/
claims.rs

1use super::Audience;
2use serde::{Deserialize, Serialize};
3
4/// Represents a structured address for the OIDC address claim.
5#[derive(Debug, Serialize, Deserialize, Clone)]
6pub struct Address {
7    /// Full mailing address, formatted for display or use.
8    #[serde(skip_serializing_if = "Option::is_none")]
9    pub formatted: Option<String>,
10    /// Street address component (e.g., house number and street name).
11    #[serde(skip_serializing_if = "Option::is_none")]
12    pub street_address: Option<String>,
13    /// City or locality component.
14    #[serde(skip_serializing_if = "Option::is_none")]
15    pub locality: Option<String>,
16    /// State, province, or region component.
17    #[serde(skip_serializing_if = "Option::is_none")]
18    pub region: Option<String>,
19    /// ZIP or postal code component.
20    #[serde(skip_serializing_if = "Option::is_none")]
21    pub postal_code: Option<String>,
22    /// Country name component.
23    #[serde(skip_serializing_if = "Option::is_none")]
24    pub country: Option<String>,
25}
26
27/// Represents a combined set of JWT, OAuth 2.0, OIDC, and provider-specific claims.
28#[derive(Debug, Serialize, Deserialize, Clone)]
29pub struct AuthClaims {
30    // Standard JWT Claims (RFC 7519)
31    /// Issuer - Identifies the authorization server that issued the token (JWT: iss).
32    #[serde(rename = "iss", skip_serializing_if = "Option::is_none")]
33    pub issuer: Option<String>,
34
35    /// Subject - Unique identifier for the user or client (JWT: sub).
36    #[serde(rename = "sub", skip_serializing_if = "Option::is_none")]
37    pub subject: Option<String>,
38
39    /// Audience - Identifies the intended recipients, can be a string or array (JWT: aud).
40    #[serde(rename = "aud", skip_serializing_if = "Option::is_none")]
41    pub audience: Option<Audience>,
42
43    /// Expiration Time - Unix timestamp when the token expires (JWT: exp).
44    #[serde(rename = "exp", skip_serializing_if = "Option::is_none")]
45    pub expiration: Option<i64>,
46
47    /// Not Before - Unix timestamp when the token becomes valid (JWT: nbf).
48    #[serde(rename = "nbf", skip_serializing_if = "Option::is_none")]
49    pub not_before: Option<i64>,
50
51    /// Issued At - Unix timestamp when the token was issued (JWT: iat).
52    #[serde(rename = "iat", skip_serializing_if = "Option::is_none")]
53    pub issued_at: Option<i64>,
54
55    /// JWT ID - Unique identifier for the token to prevent reuse (JWT: jti).
56    #[serde(rename = "jti", skip_serializing_if = "Option::is_none")]
57    pub jwt_id: Option<String>,
58
59    // OAuth 2.0 Access Token Claims (RFC 9068)
60    /// Scope - Space-separated list of scopes authorized for the token.
61    #[serde(rename = "scope", skip_serializing_if = "Option::is_none")]
62    pub scope: Option<String>,
63
64    /// Client ID - ID of the OAuth client that obtained the token.
65    #[serde(rename = "client_id", skip_serializing_if = "Option::is_none")]
66    pub client_id: Option<String>,
67
68    /// Confirmation - Provides key binding info (e.g., cnf.jkt for PoP tokens).
69    #[serde(rename = "cnf", skip_serializing_if = "Option::is_none")]
70    pub confirmation: Option<serde_json::Value>,
71
72    /// Authentication Time - Unix timestamp when the user was authenticated.
73    #[serde(rename = "auth_time", skip_serializing_if = "Option::is_none")]
74    pub auth_time: Option<i64>,
75
76    /// Authorized Party - The party to which the token was issued.
77    #[serde(rename = "azp", skip_serializing_if = "Option::is_none")]
78    pub authorized_party: Option<String>,
79
80    /// Actor - Used for delegated authorization (on behalf of another party).
81    #[serde(rename = "act", skip_serializing_if = "Option::is_none")]
82    pub actor: Option<serde_json::Value>,
83
84    /// Session ID - Links the token to a specific user session (for logout, etc.).
85    #[serde(rename = "sid", skip_serializing_if = "Option::is_none")]
86    pub session_id: Option<String>,
87
88    // OpenID Connect Standard Claims (OIDC Core 1.0)
89    /// User's full name.
90    #[serde(rename = "name", skip_serializing_if = "Option::is_none")]
91    pub name: Option<String>,
92
93    /// User's first name.
94    #[serde(rename = "given_name", skip_serializing_if = "Option::is_none")]
95    pub given_name: Option<String>,
96
97    /// User's last name.
98    #[serde(rename = "family_name", skip_serializing_if = "Option::is_none")]
99    pub family_name: Option<String>,
100
101    /// User's middle name.
102    #[serde(rename = "middle_name", skip_serializing_if = "Option::is_none")]
103    pub middle_name: Option<String>,
104
105    /// Casual name of the user.
106    #[serde(rename = "nickname", skip_serializing_if = "Option::is_none")]
107    pub nickname: Option<String>,
108
109    /// Preferred username (often login name).
110    #[serde(rename = "preferred_username", skip_serializing_if = "Option::is_none")]
111    pub preferred_username: Option<String>,
112
113    /// URL of the user's profile page.
114    #[serde(rename = "profile", skip_serializing_if = "Option::is_none")]
115    pub profile: Option<String>,
116
117    /// URL of the user's profile picture.
118    #[serde(rename = "picture", skip_serializing_if = "Option::is_none")]
119    pub picture: Option<String>,
120
121    /// URL of the user's website.
122    #[serde(rename = "website", skip_serializing_if = "Option::is_none")]
123    pub website: Option<String>,
124
125    /// User's email address.
126    #[serde(rename = "email", skip_serializing_if = "Option::is_none")]
127    pub email: Option<String>,
128
129    /// Whether the email has been verified.
130    #[serde(rename = "email_verified", skip_serializing_if = "Option::is_none")]
131    pub email_verified: Option<bool>,
132
133    /// User's gender.
134    #[serde(rename = "gender", skip_serializing_if = "Option::is_none")]
135    pub gender: Option<String>,
136
137    /// User's date of birth (e.g., "YYYY-MM-DD").
138    #[serde(rename = "birthdate", skip_serializing_if = "Option::is_none")]
139    pub birthdate: Option<String>,
140
141    /// User's time zone (e.g., "America/New_York").
142    #[serde(rename = "zoneinfo", skip_serializing_if = "Option::is_none")]
143    pub zoneinfo: Option<String>,
144
145    /// User's locale (e.g., "en-US").
146    #[serde(rename = "locale", skip_serializing_if = "Option::is_none")]
147    pub locale: Option<String>,
148
149    /// User's phone number.
150    #[serde(rename = "phone_number", skip_serializing_if = "Option::is_none")]
151    pub phone_number: Option<String>,
152
153    /// Whether the phone number has been verified.
154    #[serde(
155        rename = "phone_number_verified",
156        skip_serializing_if = "Option::is_none"
157    )]
158    pub phone_number_verified: Option<bool>,
159
160    /// User's structured address.
161    #[serde(rename = "address", skip_serializing_if = "Option::is_none")]
162    pub address: Option<Address>,
163
164    /// Last time the user's information was updated (Unix timestamp).
165    #[serde(rename = "updated_at", skip_serializing_if = "Option::is_none")]
166    pub updated_at: Option<i64>,
167
168    // Microsoft Entra ID (Azure AD) Provider-Specific Claims
169    /// Object ID of the user or service principal (Entra ID).
170    #[serde(rename = "oid", skip_serializing_if = "Option::is_none")]
171    pub object_id: Option<String>,
172
173    /// Tenant ID (directory ID) (Entra ID).
174    #[serde(rename = "tid", skip_serializing_if = "Option::is_none")]
175    pub tenant_id: Option<String>,
176
177    /// User Principal Name (login, e.g., user@domain) (Entra ID).
178    #[serde(rename = "upn", skip_serializing_if = "Option::is_none")]
179    pub user_principal_name: Option<String>,
180
181    /// Assigned roles (Entra ID).
182    #[serde(rename = "roles", skip_serializing_if = "Option::is_none")]
183    pub roles: Option<Vec<String>>,
184
185    /// Azure AD groups (GUIDs) (Entra ID).
186    #[serde(rename = "groups", skip_serializing_if = "Option::is_none")]
187    pub groups: Option<Vec<String>>,
188
189    /// Application ID (same as client_id) (Entra ID).
190    #[serde(rename = "appid", skip_serializing_if = "Option::is_none")]
191    pub application_id: Option<String>,
192
193    /// Unique name (e.g., user@domain) (Entra ID).
194    #[serde(rename = "unique_name", skip_serializing_if = "Option::is_none")]
195    pub unique_name: Option<String>,
196
197    /// Token version (e.g., "1.0" or "2.0") (Entra ID).
198    #[serde(rename = "ver", skip_serializing_if = "Option::is_none")]
199    pub version: Option<String>,
200}
201
202/// Represents an OAuth 2.0 Token Introspection response as per RFC 7662.
203///
204/// This struct captures the response from an OAuth 2.0 introspection endpoint,
205/// providing details about the validity and metadata of an access or refresh token.
206/// All fields are optional except `active`, as per the specification, to handle
207/// cases where the token is inactive or certain metadata is not provided.
208///
209/// # Example JSON
210/// ```json
211/// {
212///   "active": true,
213///   "scope": "read write",
214///   "client_id": "client123",
215///   "username": "john_doe",
216///   "token_type": "access_token",
217///   "exp": 1697054400,
218///   "iat": 1697050800,
219///   "nbf": 1697050800,
220///   "sub": "user123",
221///   "aud": ["resource_server_1", "resource_server_2"],
222///   "iss": "https://auth.example.com",
223///   "jti": "abc123"
224/// }
225/// ```
226#[derive(Debug, Serialize, Deserialize, Clone)]
227#[serde(rename_all = "snake_case")]
228pub struct IntrospectionResponse {
229    /// Indicates whether the token is active (valid, not expired, etc.).
230    /// This field is required by the OAuth 2.0 introspection specification.
231    pub active: bool,
232
233    /// Space-separated list of scopes granted to the token.
234    /// Optional, as the token may have no scopes or be inactive.
235    #[serde(default)]
236    pub scope: Option<String>,
237
238    /// Identifier of the client that requested the token.
239    /// Optional, as it may not be provided for inactive tokens.
240    #[serde(default)]
241    pub client_id: Option<String>,
242
243    /// Username of the resource owner associated with the token, if applicable.
244    /// Optional, as it may not apply to all token types or be absent for inactive tokens.
245    #[serde(default)]
246    pub username: Option<String>,
247
248    /// Type of the token, typically "access_token" or "refresh_token".
249    /// Optional, as it may not be provided for inactive tokens.
250    #[serde(default)]
251    pub token_type: Option<String>,
252
253    /// Expiration Time - Unix timestamp when the token expires (JWT: exp).
254    #[serde(rename = "exp", skip_serializing_if = "Option::is_none")]
255    pub expiration: Option<i64>,
256
257    /// Issued At - Unix timestamp when the token was issued (JWT: iat).
258    #[serde(rename = "iat", skip_serializing_if = "Option::is_none")]
259    pub issued_at: Option<i64>,
260
261    /// Not Before - Unix timestamp when the token becomes valid (JWT: nbf).
262    #[serde(rename = "nbf", skip_serializing_if = "Option::is_none")]
263    pub not_before: Option<i64>,
264
265    /// Subject identifier, often the user ID associated with the token.
266    /// Optional, as it may not be provided for inactive tokens.
267    #[serde(rename = "sub", skip_serializing_if = "Option::is_none")]
268    pub subject: Option<String>,
269
270    /// Audience(s) the token is intended for, which can be a single string or an array of strings.
271    /// Optional, as it may not be provided for inactive tokens.
272    #[serde(rename = "aud", skip_serializing_if = "Option::is_none")]
273    pub audience: Option<Audience>,
274
275    /// Issuer identifier, typically the URI of the authorization server.
276    /// Optional, as it may not be provided for inactive tokens.
277    #[serde(rename = "iss", skip_serializing_if = "Option::is_none")]
278    pub issuer: Option<String>,
279
280    /// JWT ID - Unique identifier for the token to prevent reuse (JWT: jti).
281    #[serde(rename = "jti", skip_serializing_if = "Option::is_none")]
282    pub jwt_id: Option<String>,
283}