Skip to main content

simple_oauth/
types.rs

1use std::fmt::Debug;
2
3use serde::{Deserialize, Serialize};
4
5/// Redacted field for debug outputs
6const REDACTED: &str = "[redacted]";
7
8/// Type of the internal oauth2 client
9pub(crate) type OAuthClient = oauth2::Client<
10    oauth2::basic::BasicErrorResponse,
11    OAuthTokenResponse,
12    oauth2::basic::BasicTokenIntrospectionResponse,
13    oauth2::StandardRevocableToken,
14    oauth2::basic::BasicRevocationErrorResponse,
15    oauth2::EndpointSet,
16    oauth2::EndpointNotSet,
17    oauth2::EndpointNotSet,
18    oauth2::EndpointNotSet,
19    oauth2::EndpointSet,
20>;
21
22/// Type of the internal oauth2 token response
23pub(crate) type OAuthTokenResponse =
24    oauth2::StandardTokenResponse<OidcExtraTokenFields, oauth2::basic::BasicTokenType>;
25
26/// Struct to extract the ID token if it exists
27#[derive(Clone, Debug, Default, Deserialize, Serialize)]
28pub(crate) struct OidcExtraTokenFields {
29    pub id_token: Option<String>,
30}
31impl oauth2::ExtraTokenFields for OidcExtraTokenFields {}
32
33/// OAuth2 authorization redirect URL, along with the state and PKCE verifier
34#[derive(Clone)]
35pub struct AuthorizeUrl {
36    pub url: oauth2::url::Url,
37    pub state: String,
38    pub pkce_verifier: String,
39}
40impl Debug for AuthorizeUrl {
41    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42        f.debug_struct("AuthorizeUrl")
43            .field("url", &REDACTED)
44            .field("state", &self.state)
45            .field("pkce_verifier", &REDACTED)
46            .finish()
47    }
48}
49
50/// Normalized user info returned by the OAuth provider
51#[derive(Debug, Default, Clone)]
52pub struct UserInfo {
53    /// The ID of the user at the OAuth provider
54    pub id: String,
55    /// The user's display name
56    pub name: Option<String>,
57    /// The user's username
58    pub username: Option<String>,
59    /// The user's email. Will likely not be included unless you add the proper email scope for the provider.
60    ///
61    /// ⚠️ Do not rely on this for identifying the user. Use the `id` and the name of the provider.
62    pub email: Option<String>,
63    /// Whether the user's email is verified. Not all providers return this in the user info.
64    pub email_verified: Option<bool>,
65    /// The URL of the user's picture/avatar
66    pub avatar_url: Option<String>,
67    /// The groups the user is a part of. Only included for certain OIDC providers.
68    pub groups: Option<Vec<String>>,
69}
70
71/// Standard OAuth2 token response
72#[derive(Clone)]
73pub struct StandardTokenResponse {
74    /// Access token
75    pub access_token: String,
76    /// Refresh token
77    pub refresh_token: Option<String>,
78    /// ID token ⚠️ The ID token is not validated by this crate. You must manually validate the token.
79    pub id_token: Option<String>,
80    /// The valid duration of the access token
81    pub expires_in: Option<std::time::Duration>,
82}
83impl Debug for StandardTokenResponse {
84    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
85        f.debug_struct("StandardTokenResponse")
86            .field("access_token", &REDACTED)
87            .field("refresh_token", &REDACTED)
88            .field("id_token", &REDACTED)
89            .field("expires_in", &self.expires_in)
90            .finish()
91    }
92}
93
94/// OAuth2 client ID and secret
95#[derive(Clone)]
96pub struct OAuthCredentials {
97    pub client_id: String,
98    pub client_secret: String,
99}
100impl OAuthCredentials {
101    pub fn new(client_id: impl Into<String>, client_secret: impl Into<String>) -> Self {
102        Self {
103            client_id: client_id.into(),
104            client_secret: client_secret.into(),
105        }
106    }
107}
108impl Debug for OAuthCredentials {
109    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
110        f.debug_struct("OAuthCredentials")
111            .field("client_id", &self.client_id)
112            .field("client_secret", &REDACTED)
113            .finish()
114    }
115}
116impl<S> From<(S, S)> for OAuthCredentials
117where
118    S: Into<String>,
119{
120    fn from((id, secret): (S, S)) -> Self {
121        Self::new(id, secret)
122    }
123}
124
125/// OIDC discovery document
126#[derive(Debug, Clone, Default, Deserialize)]
127pub struct OidcDiscovery {
128    pub issuer: String,
129    pub authorization_endpoint: String,
130    pub token_endpoint: String,
131    pub userinfo_endpoint: String,
132}
133
134/// Standard OIDC user info shape
135#[derive(Debug, Deserialize)]
136pub(crate) struct OidcUserInfo {
137    pub sub: String,
138    pub name: Option<String>,
139    pub preferred_username: Option<String>,
140    pub email: Option<String>,
141    pub email_verified: Option<bool>,
142    pub picture: Option<String>,
143    pub groups: Option<Vec<String>>,
144}