diff --git a/src/token.rs b/src/token.rs index 5831a75..a951b93 100644 --- a/src/token.rs +++ b/src/token.rs @@ -1,8 +1,8 @@ use std::default::Default; -use serde::{Deserialize, Serialize}; +use serde::{Deserialize}; -#[derive(Clone, Debug, Default, Deserialize, Serialize)] +#[derive(Clone, Debug, Default, Deserialize, serde::Serialize)] pub struct Token { pub scope: String, pub expiration: i64, @@ -11,7 +11,7 @@ pub struct Token { pub issued: i64, } -#[derive(Clone, Debug, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, serde::Serialize)] pub struct AccessToken { #[serde(alias = "init::is_uuid_nil")] pub user_id: uuid::Uuid, @@ -27,6 +27,21 @@ pub struct AccessToken { pub message: String, } +#[derive(Clone, Debug, serde::Serialize, Deserialize)] +pub struct UserClaims { + pub iss: String, + pub aud: String, // Audience + pub sub: String, // Subject (user ID) + #[serde(deserialize_with = "deserialize_i64_from_f64")] + pub exp: i64, // Expiration time (UTC timestamp) + #[serde(deserialize_with = "deserialize_i64_from_f64")] + pub iat: i64, // Issued at (UTC timestamp) + // pub azp: String, + // pub gty: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub roles: Option>, // Optional roles +} + impl AccessToken { /// Get the token fit for Bearer authentication pub fn bearer_token(&self) -> String { @@ -56,6 +71,25 @@ impl Token { } } +fn deserialize_i64_from_f64<'de, D>(deserializer: D) -> Result +where + D: serde::Deserializer<'de>, +{ + let val = f64::deserialize(deserializer)?; + // Handle NaN and infinity cases + if val.is_nan() || val.is_infinite() { + return Err(serde::de::Error::custom("invalid float value")); + } + // Round to nearest integer and convert + let rounded = val.round(); + // Check if the rounded value can fit in i64 + if rounded < (i64::MIN as f64) || rounded > (i64::MAX as f64) { + Err(serde::de::Error::custom("float out of i64 range")) + } else { + Ok(rounded as i64) + } +} + pub fn get_issued() -> time::Result { Ok(time::OffsetDateTime::now_utc()) }