From d2c59f0b71cdfbdd55eeff2237f14482c796118f Mon Sep 17 00:00:00 2001 From: Drew Ridley <47063089+DrewRidley@users.noreply.github.com> Date: Mon, 12 Aug 2024 04:50:27 -0400 Subject: [PATCH] Fix JWT 'aud' array (#4488) Co-authored-by: Drew Ridley Co-authored-by: Gerard Guillemas Martos --- core/src/iam/token.rs | 14 ++++++++++++-- core/src/iam/verify.rs | 20 ++++++++++---------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/core/src/iam/token.rs b/core/src/iam/token.rs index 07a567e5..27aedc0f 100644 --- a/core/src/iam/token.rs +++ b/core/src/iam/token.rs @@ -8,6 +8,13 @@ use std::collections::HashMap; pub static HEADER: Lazy
= Lazy::new(|| Header::new(Algorithm::HS512)); +#[derive(Debug, Serialize, Deserialize, Clone)] +#[serde(untagged)] +pub enum Audience { + Single(String), + Multiple(Vec), +} + #[derive(Debug, Default, Serialize, Deserialize, Clone)] #[non_exhaustive] pub struct Claims { @@ -22,7 +29,7 @@ pub struct Claims { #[serde(skip_serializing_if = "Option::is_none")] pub sub: Option, #[serde(skip_serializing_if = "Option::is_none")] - pub aud: Option, + pub aud: Option, #[serde(skip_serializing_if = "Option::is_none")] pub jti: Option, #[serde(alias = "ns")] @@ -80,7 +87,10 @@ impl From for Value { } // Add aud field if set if let Some(aud) = v.aud { - out.insert("aud".to_string(), aud.into()); + match aud { + Audience::Single(v) => out.insert("aud".to_string(), v.into()), + Audience::Multiple(v) => out.insert("aud".to_string(), v.into()), + }; } // Add iat field if set if let Some(iat) = v.iat { diff --git a/core/src/iam/verify.rs b/core/src/iam/verify.rs index 840c536e..cb5a695a 100644 --- a/core/src/iam/verify.rs +++ b/core/src/iam/verify.rs @@ -691,7 +691,7 @@ async fn authenticate_jwt( #[cfg(test)] mod tests { use super::*; - use crate::iam::token::HEADER; + use crate::iam::token::{Audience, HEADER}; use argon2::password_hash::{PasswordHasher, SaltString}; use chrono::Duration; use jsonwebtoken::{encode, EncodingKey}; @@ -2246,7 +2246,7 @@ mod tests { let key = EncodingKey::from_secret(secret.as_ref()); let claims = Claims { iss: Some("surrealdb-test".to_string()), - aud: Some("surrealdb-test".to_string()), + aud: Some(Audience::Single("surrealdb-test".to_string())), iat: Some(Utc::now().timestamp()), nbf: Some(Utc::now().timestamp()), exp: Some((Utc::now() + Duration::hours(1)).timestamp()), @@ -2315,7 +2315,7 @@ mod tests { let key = EncodingKey::from_secret(secret.as_ref()); let claims = Claims { iss: Some("surrealdb-test".to_string()), - aud: Some("invalid".to_string()), + aud: Some(Audience::Single("invalid".to_string())), iat: Some(Utc::now().timestamp()), nbf: Some(Utc::now().timestamp()), exp: Some((Utc::now() + Duration::hours(1)).timestamp()), @@ -2372,7 +2372,7 @@ mod tests { let key = EncodingKey::from_secret(secret.as_ref()); let claims = Claims { iss: Some("surrealdb-test".to_string()), - aud: Some("invalid".to_string()), + aud: Some(Audience::Single("invalid".to_string())), iat: Some(Utc::now().timestamp()), nbf: Some(Utc::now().timestamp()), exp: Some((Utc::now() + Duration::hours(1)).timestamp()), @@ -2431,7 +2431,7 @@ mod tests { let key = EncodingKey::from_secret(secret.as_ref()); let claims = Claims { iss: Some("surrealdb-test".to_string()), - aud: Some("surrealdb-test".to_string()), + aud: Some(Audience::Single("surrealdb-test".to_string())), iat: Some(Utc::now().timestamp()), nbf: Some(Utc::now().timestamp()), exp: Some((Utc::now() + Duration::hours(1)).timestamp()), @@ -2498,7 +2498,7 @@ mod tests { let key = EncodingKey::from_secret(secret.as_ref()); let claims = Claims { iss: Some("surrealdb-test".to_string()), - aud: Some("invalid".to_string()), + aud: Some(Audience::Single("invalid".to_string())), iat: Some(Utc::now().timestamp()), nbf: Some(Utc::now().timestamp()), exp: Some((Utc::now() + Duration::hours(1)).timestamp()), @@ -2554,7 +2554,7 @@ mod tests { let key = EncodingKey::from_secret(secret.as_ref()); let claims = Claims { iss: Some("surrealdb-test".to_string()), - aud: Some("invalid".to_string()), + aud: Some(Audience::Single("invalid".to_string())), iat: Some(Utc::now().timestamp()), nbf: Some(Utc::now().timestamp()), exp: Some((Utc::now() + Duration::hours(1)).timestamp()), @@ -2612,7 +2612,7 @@ mod tests { let key = EncodingKey::from_secret(secret.as_ref()); let claims = Claims { iss: Some("surrealdb-test".to_string()), - aud: Some("surrealdb-test".to_string()), + aud: Some(Audience::Single("surrealdb-test".to_string())), iat: Some(Utc::now().timestamp()), nbf: Some(Utc::now().timestamp()), exp: Some((Utc::now() + Duration::hours(1)).timestamp()), @@ -2677,7 +2677,7 @@ mod tests { let key = EncodingKey::from_secret(secret.as_ref()); let claims = Claims { iss: Some("surrealdb-test".to_string()), - aud: Some("invalid".to_string()), + aud: Some(Audience::Single("invalid".to_string())), iat: Some(Utc::now().timestamp()), nbf: Some(Utc::now().timestamp()), exp: Some((Utc::now() + Duration::hours(1)).timestamp()), @@ -2732,7 +2732,7 @@ mod tests { let key = EncodingKey::from_secret(secret.as_ref()); let claims = Claims { iss: Some("surrealdb-test".to_string()), - aud: Some("invalid".to_string()), + aud: Some(Audience::Single("invalid".to_string())), iat: Some(Utc::now().timestamp()), nbf: Some(Utc::now().timestamp()), exp: Some((Utc::now() + Duration::hours(1)).timestamp()),