2019-11-11 13:47:35 -05:00
|
|
|
use std::collections::HashSet;
|
2019-11-11 14:29:57 -05:00
|
|
|
use std::time::{SystemTime, UNIX_EPOCH};
|
2019-11-11 13:47:35 -05:00
|
|
|
|
2017-04-11 01:41:44 -04:00
|
|
|
use serde_json::map::Map;
|
2021-03-04 11:28:05 -05:00
|
|
|
use serde_json::Value;
|
2017-04-11 01:41:44 -04:00
|
|
|
|
2019-10-31 14:12:08 -04:00
|
|
|
use crate::algorithms::Algorithm;
|
|
|
|
use crate::errors::{new_error, ErrorKind, Result};
|
2017-04-11 01:41:44 -04:00
|
|
|
|
2019-11-14 13:43:43 -05:00
|
|
|
/// Contains the various validations that are applied after decoding a JWT.
|
2017-04-12 21:08:07 -04:00
|
|
|
///
|
2019-11-11 13:47:35 -05:00
|
|
|
/// All time validation happen on UTC timestamps as seconds.
|
2017-06-13 04:51:10 -04:00
|
|
|
///
|
2017-04-12 21:08:07 -04:00
|
|
|
/// ```rust
|
2021-09-28 04:04:51 -04:00
|
|
|
/// use jsonwebtoken::{Validation, Algorithm};
|
2017-06-13 04:51:10 -04:00
|
|
|
///
|
2021-09-28 04:04:51 -04:00
|
|
|
/// let mut validation = Validation::new(Algorithm::HS256);
|
|
|
|
/// validation.leeway = 5;
|
2017-04-12 21:08:07 -04:00
|
|
|
/// // Setting audience
|
2019-10-28 11:49:02 -04:00
|
|
|
/// validation.set_audience(&["Me"]); // a single string
|
2017-04-12 21:08:07 -04:00
|
|
|
/// validation.set_audience(&["Me", "You"]); // array of strings
|
2021-09-28 04:04:51 -04:00
|
|
|
/// // or issuer
|
|
|
|
/// validation.set_iss(&["Me"]); // a single string
|
|
|
|
/// validation.set_iss(&["Me", "You"]); // array of strings
|
2017-04-12 21:08:07 -04:00
|
|
|
/// ```
|
2017-04-11 01:41:44 -04:00
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
|
|
pub struct Validation {
|
2017-08-30 05:09:57 -04:00
|
|
|
/// Add some leeway (in seconds) to the `exp`, `iat` and `nbf` validation to
|
2017-04-12 21:08:07 -04:00
|
|
|
/// account for clock skew.
|
|
|
|
///
|
|
|
|
/// Defaults to `0`.
|
2019-11-11 13:47:35 -05:00
|
|
|
pub leeway: u64,
|
2017-04-12 21:08:07 -04:00
|
|
|
/// Whether to validate the `exp` field.
|
|
|
|
///
|
|
|
|
/// It will return an error if the time in the `exp` field is past.
|
|
|
|
///
|
|
|
|
/// Defaults to `true`.
|
2017-04-11 01:41:44 -04:00
|
|
|
pub validate_exp: bool,
|
2017-04-12 21:08:07 -04:00
|
|
|
/// Whether to validate the `nbf` field.
|
|
|
|
///
|
|
|
|
/// It will return an error if the current timestamp is before the time in the `nbf` field.
|
|
|
|
///
|
2019-01-18 02:31:56 -05:00
|
|
|
/// Defaults to `false`.
|
2017-04-11 01:41:44 -04:00
|
|
|
pub validate_nbf: bool,
|
2019-10-28 11:49:02 -04:00
|
|
|
/// If it contains a value, the validation will check that the `aud` field is a member of the
|
|
|
|
/// audience provided and will error otherwise.
|
2017-04-12 21:08:07 -04:00
|
|
|
///
|
2017-04-22 02:21:16 -04:00
|
|
|
/// Defaults to `None`.
|
2019-10-27 15:14:52 -04:00
|
|
|
pub aud: Option<HashSet<String>>,
|
2021-02-21 09:01:28 -05:00
|
|
|
/// If it contains a value, the validation will check that the `iss` field is a member of the
|
|
|
|
/// iss provided and will error otherwise.
|
2017-04-12 21:08:07 -04:00
|
|
|
///
|
2017-04-22 02:21:16 -04:00
|
|
|
/// Defaults to `None`.
|
2021-02-21 09:01:28 -05:00
|
|
|
pub iss: Option<HashSet<String>>,
|
2017-04-12 21:08:07 -04:00
|
|
|
/// If it contains a value, the validation will check that the `sub` field is the same as the
|
|
|
|
/// one provided and will error otherwise.
|
|
|
|
///
|
2017-04-22 02:21:16 -04:00
|
|
|
/// Defaults to `None`.
|
2017-04-11 01:41:44 -04:00
|
|
|
pub sub: Option<String>,
|
2021-03-22 16:24:20 -04:00
|
|
|
/// The validation will check that the `alg` of the header is contained
|
|
|
|
/// in the ones provided and will error otherwise. Will error if it is empty.
|
2017-04-22 02:21:16 -04:00
|
|
|
///
|
2017-10-22 07:20:01 -04:00
|
|
|
/// Defaults to `vec![Algorithm::HS256]`.
|
|
|
|
pub algorithms: Vec<Algorithm>,
|
2021-09-28 04:04:51 -04:00
|
|
|
|
|
|
|
/// Whether to validate the JWT signature. Very insecure to turn that off
|
|
|
|
pub(crate) validate_signature: bool,
|
2017-04-11 01:41:44 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Validation {
|
2017-10-22 07:20:01 -04:00
|
|
|
/// Create a default validation setup allowing the given alg
|
|
|
|
pub fn new(alg: Algorithm) -> Validation {
|
2021-09-28 04:04:51 -04:00
|
|
|
Validation {
|
|
|
|
algorithms: vec![alg],
|
|
|
|
leeway: 0,
|
|
|
|
|
|
|
|
validate_exp: true,
|
|
|
|
validate_nbf: false,
|
|
|
|
|
|
|
|
iss: None,
|
|
|
|
sub: None,
|
|
|
|
aud: None,
|
|
|
|
|
|
|
|
validate_signature: true,
|
|
|
|
}
|
2017-10-22 07:20:01 -04:00
|
|
|
}
|
|
|
|
|
2019-10-28 11:49:02 -04:00
|
|
|
/// `aud` is a collection of one or more acceptable audience members
|
|
|
|
pub fn set_audience<T: ToString>(&mut self, items: &[T]) {
|
|
|
|
self.aud = Some(items.iter().map(|x| x.to_string()).collect())
|
2017-04-11 01:41:44 -04:00
|
|
|
}
|
2021-02-21 09:01:28 -05:00
|
|
|
|
|
|
|
/// `iss` is a collection of one or more acceptable iss members
|
|
|
|
pub fn set_iss<T: ToString>(&mut self, items: &[T]) {
|
|
|
|
self.iss = Some(items.iter().map(|x| x.to_string()).collect())
|
|
|
|
}
|
2017-04-22 02:21:16 -04:00
|
|
|
|
2021-09-28 04:04:51 -04:00
|
|
|
/// Whether to validate the JWT cryptographic signature
|
|
|
|
/// Very insecure to turn that off, only do it if you know what you're doing.
|
|
|
|
/// With this flag turned off, you should not trust any of the values of the claims.
|
|
|
|
pub fn insecure_disable_signature_validation(&mut self) {
|
|
|
|
self.validate_signature = false;
|
2017-04-11 01:41:44 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-19 15:08:30 -05:00
|
|
|
/// Gets the current timestamp in the format JWT expect
|
|
|
|
pub fn get_current_timestamp() -> u64 {
|
2019-11-11 13:47:35 -05:00
|
|
|
let start = SystemTime::now();
|
|
|
|
start.duration_since(UNIX_EPOCH).expect("Time went backwards").as_secs()
|
|
|
|
}
|
|
|
|
|
2017-04-11 01:41:44 -04:00
|
|
|
pub fn validate(claims: &Map<String, Value>, options: &Validation) -> Result<()> {
|
2019-11-11 13:47:35 -05:00
|
|
|
let now = get_current_timestamp();
|
2017-04-11 01:41:44 -04:00
|
|
|
|
2018-07-25 09:42:00 -04:00
|
|
|
if options.validate_exp {
|
|
|
|
if let Some(exp) = claims.get("exp") {
|
2021-03-04 11:28:05 -05:00
|
|
|
if let Some(exp) = exp.as_u64() {
|
|
|
|
if exp < now - options.leeway {
|
|
|
|
return Err(new_error(ErrorKind::ExpiredSignature));
|
|
|
|
}
|
|
|
|
} else {
|
2018-07-25 09:42:00 -04:00
|
|
|
return Err(new_error(ErrorKind::ExpiredSignature));
|
|
|
|
}
|
|
|
|
} else {
|
2018-07-25 08:43:58 -04:00
|
|
|
return Err(new_error(ErrorKind::ExpiredSignature));
|
2017-04-11 01:41:44 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-25 09:42:00 -04:00
|
|
|
if options.validate_nbf {
|
|
|
|
if let Some(nbf) = claims.get("nbf") {
|
2021-03-04 11:28:05 -05:00
|
|
|
if let Some(nbf) = nbf.as_u64() {
|
|
|
|
if nbf > now + options.leeway {
|
|
|
|
return Err(new_error(ErrorKind::ImmatureSignature));
|
|
|
|
}
|
|
|
|
} else {
|
2018-07-25 09:42:00 -04:00
|
|
|
return Err(new_error(ErrorKind::ImmatureSignature));
|
|
|
|
}
|
|
|
|
} else {
|
2018-07-25 08:43:58 -04:00
|
|
|
return Err(new_error(ErrorKind::ImmatureSignature));
|
2017-04-11 01:41:44 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-25 09:42:00 -04:00
|
|
|
if let Some(ref correct_sub) = options.sub {
|
2021-03-04 11:28:05 -05:00
|
|
|
if let Some(Value::String(sub)) = claims.get("sub") {
|
|
|
|
if sub != correct_sub {
|
2018-07-25 08:43:58 -04:00
|
|
|
return Err(new_error(ErrorKind::InvalidSubject));
|
2017-04-11 01:41:44 -04:00
|
|
|
}
|
2018-07-25 09:42:00 -04:00
|
|
|
} else {
|
|
|
|
return Err(new_error(ErrorKind::InvalidSubject));
|
2017-04-11 01:41:44 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-21 09:01:28 -05:00
|
|
|
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));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-25 09:42:00 -04:00
|
|
|
if let Some(ref correct_aud) = options.aud {
|
|
|
|
if let Some(aud) = claims.get("aud") {
|
2019-11-28 13:27:08 -05:00
|
|
|
match aud {
|
2021-03-04 06:20:26 -05:00
|
|
|
Value::String(aud) => {
|
|
|
|
if !correct_aud.contains(aud) {
|
2019-11-28 13:27:08 -05:00
|
|
|
return Err(new_error(ErrorKind::InvalidAudience));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Value::Array(_) => {
|
2021-03-04 06:20:26 -05:00
|
|
|
use serde::Deserialize;
|
|
|
|
let aud = HashSet::<String>::deserialize(aud)?;
|
|
|
|
if aud.intersection(correct_aud).next().is_none() {
|
2019-11-28 13:27:08 -05:00
|
|
|
return Err(new_error(ErrorKind::InvalidAudience));
|
|
|
|
}
|
|
|
|
}
|
2019-12-29 12:42:35 -05:00
|
|
|
_ => return Err(new_error(ErrorKind::InvalidAudience)),
|
2019-11-28 13:27:08 -05:00
|
|
|
};
|
2018-07-25 09:42:00 -04:00
|
|
|
} else {
|
|
|
|
return Err(new_error(ErrorKind::InvalidAudience));
|
2017-04-11 01:41:44 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
2018-10-28 14:58:35 -04:00
|
|
|
use serde_json::map::Map;
|
|
|
|
use serde_json::to_value;
|
2017-04-11 01:41:44 -04:00
|
|
|
|
2019-11-11 14:29:57 -05:00
|
|
|
use super::{get_current_timestamp, validate, Validation};
|
2017-04-11 01:41:44 -04:00
|
|
|
|
2019-10-31 14:12:08 -04:00
|
|
|
use crate::errors::ErrorKind;
|
2021-09-28 04:04:51 -04:00
|
|
|
use crate::Algorithm;
|
2017-04-11 01:41:44 -04:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn exp_in_future_ok() {
|
|
|
|
let mut claims = Map::new();
|
2019-11-11 13:47:35 -05:00
|
|
|
claims.insert("exp".to_string(), to_value(get_current_timestamp() + 10000).unwrap());
|
2021-09-28 04:04:51 -04:00
|
|
|
let res = validate(&claims, &Validation::new(Algorithm::HS256));
|
2017-04-11 01:41:44 -04:00
|
|
|
assert!(res.is_ok());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn exp_in_past_fails() {
|
|
|
|
let mut claims = Map::new();
|
2019-11-11 13:47:35 -05:00
|
|
|
claims.insert("exp".to_string(), to_value(get_current_timestamp() - 100000).unwrap());
|
2021-09-28 04:04:51 -04:00
|
|
|
let res = validate(&claims, &Validation::new(Algorithm::HS256));
|
2017-04-11 01:41:44 -04:00
|
|
|
assert!(res.is_err());
|
|
|
|
|
|
|
|
match res.unwrap_err().kind() {
|
2020-08-31 06:04:57 -04:00
|
|
|
ErrorKind::ExpiredSignature => (),
|
|
|
|
_ => unreachable!(),
|
2017-04-11 01:41:44 -04:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn exp_in_past_but_in_leeway_ok() {
|
|
|
|
let mut claims = Map::new();
|
2019-11-11 13:47:35 -05:00
|
|
|
claims.insert("exp".to_string(), to_value(get_current_timestamp() - 500).unwrap());
|
2021-09-28 04:04:51 -04:00
|
|
|
let mut validation = Validation::new(Algorithm::HS256);
|
|
|
|
validation.leeway = 1000 * 60;
|
2017-04-11 01:41:44 -04:00
|
|
|
let res = validate(&claims, &validation);
|
|
|
|
assert!(res.is_ok());
|
|
|
|
}
|
|
|
|
|
2018-07-25 09:42:00 -04:00
|
|
|
// https://github.com/Keats/jsonwebtoken/issues/51
|
|
|
|
#[test]
|
|
|
|
fn validation_called_even_if_field_is_empty() {
|
|
|
|
let claims = Map::new();
|
2021-09-28 04:04:51 -04:00
|
|
|
let res = validate(&claims, &Validation::new(Algorithm::HS256));
|
2018-07-25 09:42:00 -04:00
|
|
|
assert!(res.is_err());
|
|
|
|
match res.unwrap_err().kind() {
|
2020-08-31 06:04:57 -04:00
|
|
|
ErrorKind::ExpiredSignature => (),
|
|
|
|
_ => unreachable!(),
|
2018-07-25 09:42:00 -04:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2017-04-11 01:41:44 -04:00
|
|
|
#[test]
|
|
|
|
fn nbf_in_past_ok() {
|
|
|
|
let mut claims = Map::new();
|
2019-11-11 13:47:35 -05:00
|
|
|
claims.insert("nbf".to_string(), to_value(get_current_timestamp() - 10000).unwrap());
|
2021-09-28 04:04:51 -04:00
|
|
|
let mut validation = Validation::new(Algorithm::HS256);
|
|
|
|
validation.validate_exp = false;
|
|
|
|
validation.validate_nbf = true;
|
2018-07-25 09:42:00 -04:00
|
|
|
let res = validate(&claims, &validation);
|
2017-04-11 01:41:44 -04:00
|
|
|
assert!(res.is_ok());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn nbf_in_future_fails() {
|
|
|
|
let mut claims = Map::new();
|
2019-11-11 13:47:35 -05:00
|
|
|
claims.insert("nbf".to_string(), to_value(get_current_timestamp() + 100000).unwrap());
|
2021-09-28 04:04:51 -04:00
|
|
|
let mut validation = Validation::new(Algorithm::HS256);
|
|
|
|
validation.validate_exp = false;
|
|
|
|
validation.validate_nbf = true;
|
2018-07-25 09:42:00 -04:00
|
|
|
let res = validate(&claims, &validation);
|
2017-04-11 01:41:44 -04:00
|
|
|
assert!(res.is_err());
|
|
|
|
|
|
|
|
match res.unwrap_err().kind() {
|
2020-08-31 06:04:57 -04:00
|
|
|
ErrorKind::ImmatureSignature => (),
|
|
|
|
_ => unreachable!(),
|
2017-04-11 01:41:44 -04:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn nbf_in_future_but_in_leeway_ok() {
|
|
|
|
let mut claims = Map::new();
|
2019-11-11 13:47:35 -05:00
|
|
|
claims.insert("nbf".to_string(), to_value(get_current_timestamp() + 500).unwrap());
|
2021-09-28 04:04:51 -04:00
|
|
|
let mut validation = Validation::new(Algorithm::HS256);
|
|
|
|
validation.validate_exp = false;
|
|
|
|
validation.validate_nbf = true;
|
|
|
|
validation.leeway = 1000 * 60;
|
2017-04-11 01:41:44 -04:00
|
|
|
let res = validate(&claims, &validation);
|
|
|
|
assert!(res.is_ok());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn iss_ok() {
|
|
|
|
let mut claims = Map::new();
|
|
|
|
claims.insert("iss".to_string(), to_value("Keats").unwrap());
|
2021-02-21 09:01:28 -05:00
|
|
|
|
2021-09-28 04:04:51 -04:00
|
|
|
let mut validation = Validation::new(Algorithm::HS256);
|
|
|
|
validation.validate_exp = false;
|
|
|
|
validation.set_iss(&["Keats"]);
|
2017-04-11 01:41:44 -04:00
|
|
|
let res = validate(&claims, &validation);
|
|
|
|
assert!(res.is_ok());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn iss_not_matching_fails() {
|
|
|
|
let mut claims = Map::new();
|
|
|
|
claims.insert("iss".to_string(), to_value("Hacked").unwrap());
|
2021-02-21 09:01:28 -05:00
|
|
|
|
2021-09-28 04:04:51 -04:00
|
|
|
let mut validation = Validation::new(Algorithm::HS256);
|
|
|
|
validation.validate_exp = false;
|
|
|
|
validation.set_iss(&["Keats"]);
|
2018-07-25 09:42:00 -04:00
|
|
|
let res = validate(&claims, &validation);
|
|
|
|
assert!(res.is_err());
|
|
|
|
|
|
|
|
match res.unwrap_err().kind() {
|
2020-08-31 06:04:57 -04:00
|
|
|
ErrorKind::InvalidIssuer => (),
|
|
|
|
_ => unreachable!(),
|
2018-07-25 09:42:00 -04:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn iss_missing_fails() {
|
|
|
|
let claims = Map::new();
|
2021-02-21 09:01:28 -05:00
|
|
|
|
2021-09-28 04:04:51 -04:00
|
|
|
let mut validation = Validation::new(Algorithm::HS256);
|
|
|
|
validation.validate_exp = false;
|
|
|
|
validation.set_iss(&["Keats"]);
|
2017-04-11 01:41:44 -04:00
|
|
|
let res = validate(&claims, &validation);
|
|
|
|
assert!(res.is_err());
|
|
|
|
|
|
|
|
match res.unwrap_err().kind() {
|
2020-08-31 06:04:57 -04:00
|
|
|
ErrorKind::InvalidIssuer => (),
|
|
|
|
_ => unreachable!(),
|
2017-04-11 01:41:44 -04:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn sub_ok() {
|
|
|
|
let mut claims = Map::new();
|
|
|
|
claims.insert("sub".to_string(), to_value("Keats").unwrap());
|
2021-09-28 04:04:51 -04:00
|
|
|
let mut validation = Validation::new(Algorithm::HS256);
|
|
|
|
validation.validate_exp = false;
|
|
|
|
validation.sub = Some("Keats".to_owned());
|
|
|
|
|
2017-04-11 01:41:44 -04:00
|
|
|
let res = validate(&claims, &validation);
|
|
|
|
assert!(res.is_ok());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn sub_not_matching_fails() {
|
|
|
|
let mut claims = Map::new();
|
|
|
|
claims.insert("sub".to_string(), to_value("Hacked").unwrap());
|
2021-09-28 04:04:51 -04:00
|
|
|
let mut validation = Validation::new(Algorithm::HS256);
|
|
|
|
validation.validate_exp = false;
|
|
|
|
validation.sub = Some("Keats".to_owned());
|
|
|
|
|
2018-07-25 09:42:00 -04:00
|
|
|
let res = validate(&claims, &validation);
|
|
|
|
assert!(res.is_err());
|
|
|
|
|
|
|
|
match res.unwrap_err().kind() {
|
2020-08-31 06:04:57 -04:00
|
|
|
ErrorKind::InvalidSubject => (),
|
|
|
|
_ => unreachable!(),
|
2018-07-25 09:42:00 -04:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn sub_missing_fails() {
|
|
|
|
let claims = Map::new();
|
2021-09-28 04:04:51 -04:00
|
|
|
let mut validation = Validation::new(Algorithm::HS256);
|
|
|
|
validation.validate_exp = false;
|
|
|
|
validation.sub = Some("Keats".to_owned());
|
|
|
|
|
2017-04-11 01:41:44 -04:00
|
|
|
let res = validate(&claims, &validation);
|
|
|
|
assert!(res.is_err());
|
|
|
|
|
|
|
|
match res.unwrap_err().kind() {
|
2020-08-31 06:04:57 -04:00
|
|
|
ErrorKind::InvalidSubject => (),
|
|
|
|
_ => unreachable!(),
|
2017-04-11 01:41:44 -04:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn aud_string_ok() {
|
|
|
|
let mut claims = Map::new();
|
2019-10-28 11:49:02 -04:00
|
|
|
claims.insert("aud".to_string(), to_value(["Everyone"]).unwrap());
|
2021-09-28 04:04:51 -04:00
|
|
|
let mut validation = Validation::new(Algorithm::HS256);
|
|
|
|
validation.validate_exp = false;
|
2019-10-28 11:49:02 -04:00
|
|
|
validation.set_audience(&["Everyone"]);
|
2017-04-11 01:41:44 -04:00
|
|
|
let res = validate(&claims, &validation);
|
|
|
|
assert!(res.is_ok());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn aud_array_of_string_ok() {
|
|
|
|
let mut claims = Map::new();
|
|
|
|
claims.insert("aud".to_string(), to_value(["UserA", "UserB"]).unwrap());
|
2021-09-28 04:04:51 -04:00
|
|
|
let mut validation = Validation::new(Algorithm::HS256);
|
|
|
|
validation.validate_exp = false;
|
2017-04-11 01:41:44 -04:00
|
|
|
validation.set_audience(&["UserA", "UserB"]);
|
|
|
|
let res = validate(&claims, &validation);
|
|
|
|
assert!(res.is_ok());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn aud_type_mismatch_fails() {
|
|
|
|
let mut claims = Map::new();
|
2019-10-28 11:49:02 -04:00
|
|
|
claims.insert("aud".to_string(), to_value(["Everyone"]).unwrap());
|
2021-09-28 04:04:51 -04:00
|
|
|
let mut validation = Validation::new(Algorithm::HS256);
|
|
|
|
validation.validate_exp = false;
|
2017-04-11 01:41:44 -04:00
|
|
|
validation.set_audience(&["UserA", "UserB"]);
|
|
|
|
let res = validate(&claims, &validation);
|
|
|
|
assert!(res.is_err());
|
|
|
|
|
|
|
|
match res.unwrap_err().kind() {
|
2020-08-31 06:04:57 -04:00
|
|
|
ErrorKind::InvalidAudience => (),
|
|
|
|
_ => unreachable!(),
|
2017-04-11 01:41:44 -04:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn aud_correct_type_not_matching_fails() {
|
|
|
|
let mut claims = Map::new();
|
2019-10-28 11:49:02 -04:00
|
|
|
claims.insert("aud".to_string(), to_value(["Everyone"]).unwrap());
|
2021-09-28 04:04:51 -04:00
|
|
|
let mut validation = Validation::new(Algorithm::HS256);
|
|
|
|
validation.validate_exp = false;
|
2019-10-28 11:49:02 -04:00
|
|
|
validation.set_audience(&["None"]);
|
2018-07-25 09:42:00 -04:00
|
|
|
let res = validate(&claims, &validation);
|
|
|
|
assert!(res.is_err());
|
|
|
|
|
|
|
|
match res.unwrap_err().kind() {
|
2020-08-31 06:04:57 -04:00
|
|
|
ErrorKind::InvalidAudience => (),
|
|
|
|
_ => unreachable!(),
|
2018-07-25 09:42:00 -04:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn aud_missing_fails() {
|
|
|
|
let claims = Map::new();
|
2021-09-28 04:04:51 -04:00
|
|
|
let mut validation = Validation::new(Algorithm::HS256);
|
|
|
|
validation.validate_exp = false;
|
2019-10-28 11:49:02 -04:00
|
|
|
validation.set_audience(&["None"]);
|
2017-04-11 01:41:44 -04:00
|
|
|
let res = validate(&claims, &validation);
|
|
|
|
assert!(res.is_err());
|
|
|
|
|
|
|
|
match res.unwrap_err().kind() {
|
2020-08-31 06:04:57 -04:00
|
|
|
ErrorKind::InvalidAudience => (),
|
|
|
|
_ => unreachable!(),
|
2017-04-11 01:41:44 -04:00
|
|
|
};
|
|
|
|
}
|
2019-11-03 10:36:19 -05:00
|
|
|
|
|
|
|
// https://github.com/Keats/jsonwebtoken/issues/51
|
|
|
|
#[test]
|
|
|
|
fn does_validation_in_right_order() {
|
|
|
|
let mut claims = Map::new();
|
2019-11-11 13:47:35 -05:00
|
|
|
claims.insert("exp".to_string(), to_value(get_current_timestamp() + 10000).unwrap());
|
2021-02-21 09:01:28 -05:00
|
|
|
|
2021-09-28 04:04:51 -04:00
|
|
|
let mut validation = Validation::new(Algorithm::HS256);
|
|
|
|
validation.leeway = 5;
|
|
|
|
validation.set_iss(&["iss no check"]);
|
|
|
|
validation.set_audience(&["iss no check"]);
|
|
|
|
|
|
|
|
let res = validate(&claims, &validation);
|
2021-02-21 09:01:28 -05:00
|
|
|
|
2019-11-03 10:36:19 -05:00
|
|
|
// It errors because it needs to validate iss/sub which are missing
|
|
|
|
assert!(res.is_err());
|
|
|
|
match res.unwrap_err().kind() {
|
2020-08-31 06:04:57 -04:00
|
|
|
ErrorKind::InvalidIssuer => (),
|
|
|
|
t => panic!("{:?}", t),
|
2019-11-03 10:36:19 -05:00
|
|
|
};
|
|
|
|
}
|
2019-11-28 13:27:08 -05:00
|
|
|
|
|
|
|
// https://github.com/Keats/jsonwebtoken/issues/110
|
|
|
|
#[test]
|
|
|
|
fn aud_use_validation_struct() {
|
|
|
|
let mut claims = Map::new();
|
2019-12-29 12:42:35 -05:00
|
|
|
claims.insert(
|
|
|
|
"aud".to_string(),
|
|
|
|
to_value("my-googleclientid1234.apps.googleusercontent.com").unwrap(),
|
|
|
|
);
|
2019-11-28 13:27:08 -05:00
|
|
|
|
|
|
|
let aud = "my-googleclientid1234.apps.googleusercontent.com".to_string();
|
|
|
|
let mut aud_hashset = std::collections::HashSet::new();
|
|
|
|
aud_hashset.insert(aud);
|
2021-09-28 04:04:51 -04:00
|
|
|
let mut validation = Validation::new(Algorithm::HS256);
|
|
|
|
validation.validate_exp = false;
|
|
|
|
validation.set_audience(&["my-googleclientid1234.apps.googleusercontent.com"]);
|
2019-11-28 13:27:08 -05:00
|
|
|
|
|
|
|
let res = validate(&claims, &validation);
|
|
|
|
println!("{:?}", res);
|
|
|
|
assert!(res.is_ok());
|
|
|
|
}
|
2017-04-11 01:41:44 -04:00
|
|
|
}
|