use std::collections::HashMap;
use serde::{Deserialize, Deserializer};
use serde_json::Value;
use crate::helpers::base64_url_decode;
#[derive(Debug, Deserialize, Clone, Default)]
pub struct TokenSet {
#[serde(skip_serializing_if = "Option::is_none")]
pub access_token: Option<String>,
#[serde(
skip_serializing_if = "Option::is_none",
deserialize_with = "deserialize_token_type",
default
)]
pub token_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub id_token: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub refresh_token: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub expires_in: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub session_state: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub scope: Option<String>,
#[serde(skip_serializing_if = "Option::is_none", flatten)]
pub other: Option<HashMap<String, Value>>,
}
fn deserialize_token_type<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
where
D: Deserializer<'de>,
{
let opt: Option<String> = Option::deserialize(deserializer)?;
Ok(opt.map(|s| s.to_lowercase()))
}
impl TokenSet {
pub fn claims(&self) -> Option<HashMap<String, Value>> {
if let Some(id_token) = &self.id_token {
let id_token_components: Vec<&str> = id_token.split('.').collect();
let payload = id_token_components.get(1)?;
return match base64_url_decode(payload) {
Ok(decoded) => {
serde_json::from_slice::<HashMap<String, Value>>(decoded.as_bytes()).ok()
}
Err(_) => None,
};
}
None
}
}