use secrecy::SecretString;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize)]
pub struct OAuthTokenRequest {
pub grant_type: String,
pub client_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub code: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub redirect_uri: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub code_verifier: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub refresh_token: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub scope: Option<String>,
#[serde(flatten)]
pub extra: serde_json::Map<String, serde_json::Value>,
}
#[derive(Clone, Deserialize)]
pub struct OAuthTokenResponse {
#[serde(deserialize_with = "deserialize_secret")]
pub access_token: SecretString,
#[serde(default, deserialize_with = "deserialize_option_secret")]
pub refresh_token: Option<SecretString>,
pub expires_in: u64,
pub token_type: String,
#[serde(flatten)]
pub extra: serde_json::Map<String, serde_json::Value>,
}
impl std::fmt::Debug for OAuthTokenResponse {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("OAuthTokenResponse")
.field("access_token", &"[REDACTED]")
.field(
"refresh_token",
&self.refresh_token.as_ref().map(|_| "[REDACTED]"),
)
.field("expires_in", &self.expires_in)
.field("token_type", &self.token_type)
.finish()
}
}
fn deserialize_secret<'de, D>(deserializer: D) -> Result<SecretString, D::Error>
where
D: serde::Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
Ok(SecretString::from(s))
}
fn deserialize_option_secret<'de, D>(deserializer: D) -> Result<Option<SecretString>, D::Error>
where
D: serde::Deserializer<'de>,
{
let s: Option<String> = Option::deserialize(deserializer)?;
Ok(s.map(SecretString::from))
}