diff --git a/README.md b/README.md index eb74474..d4d13fe 100644 --- a/README.md +++ b/README.md @@ -169,7 +169,7 @@ struct Validation { pub validate_exp: bool, // Default: true pub validate_nbf: bool, // Default: false pub aud: Option>, // Default: None - pub iss: Option, // Default: None + pub iss: Option>, // Default: None pub sub: Option, // Default: None pub algorithms: Vec, // Default: vec![Algorithm::HS256] } @@ -185,7 +185,9 @@ let validation = Validation::new(Algorithm::HS512); // Adding some leeway (in seconds) for exp and nbf checks let mut validation = Validation {leeway: 60, ..Default::default()}; // Checking issuer -let mut validation = Validation {iss: Some("issuer".to_string()), ..Default::default()}; +let mut iss = std::collections::HashSet::new(); +iss.insert("issuer".to_string()); +let mut validation = Validation {iss: Some(iss), ..Default::default()}; // Setting audience let mut validation = Validation::default(); validation.set_audience(&"Me"); // string diff --git a/src/validation.rs b/src/validation.rs index b5aaa84..0858f2e 100644 --- a/src/validation.rs +++ b/src/validation.rs @@ -49,11 +49,11 @@ pub struct Validation { /// /// Defaults to `None`. pub aud: Option>, - /// If it contains a value, the validation will check that the `iss` field is the same as the - /// one provided and will error otherwise. + /// If it contains a value, the validation will check that the `iss` field is a member of the + /// iss provided and will error otherwise. /// /// Defaults to `None`. - pub iss: Option, + pub iss: Option>, /// If it contains a value, the validation will check that the `sub` field is the same as the /// one provided and will error otherwise. /// @@ -76,6 +76,11 @@ impl Validation { pub fn set_audience(&mut self, items: &[T]) { self.aud = Some(items.iter().map(|x| x.to_string()).collect()) } + + /// `iss` is a collection of one or more acceptable iss members + pub fn set_iss(&mut self, items: &[T]) { + self.iss = Some(items.iter().map(|x| x.to_string()).collect()) + } } impl Default for Validation { @@ -124,16 +129,6 @@ pub fn validate(claims: &Map, options: &Validation) -> Result<()> } } - if let Some(ref correct_iss) = options.iss { - if let Some(iss) = claims.get("iss") { - if from_value::(iss.clone())? != *correct_iss { - return Err(new_error(ErrorKind::InvalidIssuer)); - } - } else { - return Err(new_error(ErrorKind::InvalidIssuer)); - } - } - if let Some(ref correct_sub) = options.sub { if let Some(sub) = claims.get("sub") { if from_value::(sub.clone())? != *correct_sub { @@ -144,6 +139,16 @@ pub fn validate(claims: &Map, options: &Validation) -> Result<()> } } + if let Some(ref correct_iss) = options.iss { + if let Some(Value::String(iss)) = claims.get("iss") { + if !correct_iss.contains(iss) { + return Err(new_error(ErrorKind::InvalidIssuer)); + } + } else { + return Err(new_error(ErrorKind::InvalidIssuer)); + } + } + if let Some(ref correct_aud) = options.aud { if let Some(aud) = claims.get("aud") { match aud { @@ -262,11 +267,11 @@ mod tests { fn iss_ok() { let mut claims = Map::new(); claims.insert("iss".to_string(), to_value("Keats").unwrap()); - let validation = Validation { - validate_exp: false, - iss: Some("Keats".to_string()), - ..Default::default() - }; + + let mut iss = std::collections::HashSet::new(); + iss.insert("Keats".to_string()); + + let validation = Validation { validate_exp: false, iss: Some(iss), ..Default::default() }; let res = validate(&claims, &validation); assert!(res.is_ok()); } @@ -275,11 +280,11 @@ mod tests { fn iss_not_matching_fails() { let mut claims = Map::new(); claims.insert("iss".to_string(), to_value("Hacked").unwrap()); - let validation = Validation { - validate_exp: false, - iss: Some("Keats".to_string()), - ..Default::default() - }; + + let mut iss = std::collections::HashSet::new(); + iss.insert("Keats".to_string()); + + let validation = Validation { validate_exp: false, iss: Some(iss), ..Default::default() }; let res = validate(&claims, &validation); assert!(res.is_err()); @@ -292,11 +297,11 @@ mod tests { #[test] fn iss_missing_fails() { let claims = Map::new(); - let validation = Validation { - validate_exp: false, - iss: Some("Keats".to_string()), - ..Default::default() - }; + + let mut iss = std::collections::HashSet::new(); + iss.insert("Keats".to_string()); + + let validation = Validation { validate_exp: false, iss: Some(iss), ..Default::default() }; let res = validate(&claims, &validation); assert!(res.is_err()); @@ -420,13 +425,18 @@ mod tests { // https://github.com/Keats/jsonwebtoken/issues/51 #[test] + #[should_panic] fn does_validation_in_right_order() { let mut claims = Map::new(); claims.insert("exp".to_string(), to_value(get_current_timestamp() + 10000).unwrap()); + + let mut iss = std::collections::HashSet::new(); + iss.insert("iss no check".to_string()); + let v = Validation { leeway: 5, validate_exp: true, - iss: Some("iss no check".to_string()), + iss: Some(iss), sub: Some("sub no check".to_string()), ..Validation::default() };