Skip to content

Commit

Permalink
Allow updated_at to be a number within a string
Browse files Browse the repository at this point in the history
  • Loading branch information
multun committed Apr 24, 2024
1 parent c4e28f4 commit c107ff5
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 1 deletion.
57 changes: 56 additions & 1 deletion src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,58 @@ where
}
}

// Some providers return numbers as strings
pub(crate) mod serde_string_number {
use serde::{de, Deserializer};

use std::fmt;

pub fn deserialize<'de, D>(deserializer: D) -> Result<serde_json::Number, D::Error>
where
D: Deserializer<'de>,
{
struct StringLikeNumberVisitor;

impl<'de> de::Visitor<'de> for StringLikeNumberVisitor {
type Value = serde_json::Number;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a JSON number")
}

fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(v.into())
}

fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(v.into())
}

fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
where
E: de::Error,
{
serde_json::Number::from_f64(v)
.ok_or_else(|| de::Error::custom("not a JSON number"))
}

fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
serde_json::from_str(v).map_err(|_| de::Error::custom("not a JSON number"))
}
}
deserializer.deserialize_any(StringLikeNumberVisitor)
}
}

// Some providers return boolean values as strings. Provide support for
// parsing using stdlib.
#[cfg(feature = "accept-string-booleans")]
Expand Down Expand Up @@ -331,7 +383,10 @@ impl Display for Boolean {
#[derive(Debug, Deserialize, Serialize)]
#[serde(untagged)]
pub(crate) enum Timestamp {
Seconds(serde_json::Number),
Seconds(
#[serde(deserialize_with = "crate::helpers::serde_string_number::deserialize")]
serde_json::Number,
),
#[cfg(feature = "accept-rfc3339-timestamps")]
Rfc3339(String),
}
Expand Down
31 changes: 31 additions & 0 deletions src/id_token/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,37 @@ fn test_accept_rfc3339_timestamp() {
);
}

#[test]
fn test_accept_string_updated_at() {
for (updated_at, sec, nsec) in [
("1713963222.5", 1713963222, 500_000_000),
("42.5", 42, 500_000_000),
("42", 42, 0),
("-42", -42, 0),
] {
let payload = format!(
"{{
\"iss\": \"https://server.example.com\",
\"sub\": \"24400320\",
\"aud\": \"s6BhdRkqt3\",
\"exp\": 1311281970,
\"iat\": 1311280970,
\"updated_at\": \"{updated_at}\"
}}"
);
let claims: CoreIdTokenClaims =
serde_json::from_str(payload.as_str()).expect("failed to deserialize");
assert_eq!(
claims.updated_at(),
Some(
Utc.timestamp_opt(sec, nsec)
.single()
.expect("valid timestamp")
)
);
}
}

#[test]
fn test_unknown_claims_serde() {
let expected_serialized_claims = "{\
Expand Down

0 comments on commit c107ff5

Please sign in to comment.