stalwart_lib/common/src/auth/oauth/
introspect.rs1use crate::trc::{AddContext, AuthEvent, EventType};
8use serde::{Deserialize, Serialize};
9
10use crate::common::{Server, auth::AccessToken};
11
12#[derive(Debug, Default, Clone, Eq, PartialEq, Deserialize, Serialize)]
13pub struct OAuthIntrospect {
14 #[serde(default)]
15 pub active: bool,
16
17 #[serde(default)]
18 #[serde(skip_serializing_if = "Option::is_none")]
19 pub scope: Option<String>,
20
21 #[serde(default)]
22 #[serde(skip_serializing_if = "Option::is_none")]
23 pub client_id: Option<String>,
24
25 #[serde(default)]
26 #[serde(skip_serializing_if = "Option::is_none")]
27 pub username: Option<String>,
28
29 #[serde(default)]
30 #[serde(skip_serializing_if = "Option::is_none")]
31 pub token_type: Option<String>,
32
33 #[serde(default)]
34 #[serde(skip_serializing_if = "Option::is_none")]
35 pub exp: Option<i64>,
36
37 #[serde(default)]
38 #[serde(skip_serializing_if = "Option::is_none")]
39 pub iat: Option<i64>,
40
41 #[serde(default)]
42 #[serde(skip_serializing_if = "Option::is_none")]
43 pub nbf: Option<i64>,
44
45 #[serde(default)]
46 #[serde(skip_serializing_if = "Option::is_none")]
47 pub sub: Option<String>,
48}
49
50impl Server {
51 pub async fn introspect_access_token(
52 &self,
53 token: &str,
54 access_token: &AccessToken,
55 ) -> crate::trc::Result<OAuthIntrospect> {
56 match self.validate_access_token(None, token).await {
57 Ok(token_info) => Ok(OAuthIntrospect {
58 active: true,
59 client_id: Some(token_info.client_id),
60 username: if access_token.primary_id() == token_info.account_id {
61 access_token.name.clone()
62 } else {
63 self.get_access_token(token_info.account_id)
64 .await
65 .caused_by(crate::trc::location!())?
66 .name
67 .clone()
68 }
69 .into(),
70 token_type: Some("bearer".into()),
71 exp: Some(token_info.expiry as i64),
72 iat: Some(token_info.issued_at as i64),
73 ..Default::default()
74 }),
75 Err(err)
76 if matches!(
77 err.event_type(),
78 EventType::Auth(AuthEvent::Error) | EventType::Auth(AuthEvent::TokenExpired)
79 ) =>
80 {
81 Ok(OAuthIntrospect::default())
82 }
83 Err(err) => Err(err),
84 }
85 }
86}