2019-10-27 15:14:52 -04:00
|
|
|
use std::collections::HashSet;
|
2017-06-24 02:15:45 -04:00
|
|
|
use chrono::Utc;
|
2017-04-11 01:41:44 -04:00
|
|
|
use serde::ser::Serialize;
|
|
|
|
use serde_json::map::Map;
|
2018-10-28 14:58:35 -04:00
|
|
|
use serde_json::{from_value, to_value, Value};
|
2017-04-11 01:41:44 -04:00
|
|
|
|
2019-07-06 14:36:32 -04:00
|
|
|
use crate::algorithms::Algorithm;
|
|
|
|
use crate::errors::{new_error, ErrorKind, Result};
|
2017-04-11 01:41:44 -04:00
|
|
|
|
2017-04-12 21:08:07 -04:00
|
|
|
/// Contains the various validations that are applied after decoding a token.
|
|
|
|
///
|
|
|
|
/// All time validation happen on UTC timestamps.
|
2017-06-13 04:51:10 -04:00
|
|
|
///
|
2017-04-12 21:08:07 -04:00
|
|
|
/// ```rust
|
|
|
|
/// use jsonwebtoken::Validation;
|
|
|
|
///
|
|
|
|
/// // Default value
|
|
|
|
/// let validation = Validation::default();
|
2017-06-13 04:51:10 -04:00
|
|
|
///
|
2017-04-12 21:08:07 -04:00
|
|
|
/// // Changing one parameter
|
2017-08-30 05:09:57 -04:00
|
|
|
/// let mut validation = Validation {leeway: 60, ..Default::default()};
|
2017-06-13 04:51:10 -04:00
|
|
|
///
|
2017-04-12 21:08:07 -04:00
|
|
|
/// // Setting audience
|
|
|
|
/// let mut validation = Validation::default();
|
|
|
|
/// validation.set_audience(&"Me"); // string
|
|
|
|
/// validation.set_audience(&["Me", "You"]); // array of strings
|
|
|
|
/// ```
|
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`.
|
2017-04-11 01:41:44 -04:00
|
|
|
pub leeway: i64,
|
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,
|
2017-04-12 21:08:07 -04:00
|
|
|
/// If it contains a value, the validation will check that the `aud` field is the same as the
|
|
|
|
/// one provided and will error otherwise.
|
|
|
|
/// Since `aud` can be either a String or a Vec<String> in the JWT spec, you will need to use
|
|
|
|
/// the [set_audience](struct.Validation.html#method.set_audience) method to set it.
|
|
|
|
///
|
2017-04-22 02:21:16 -04:00
|
|
|
/// Defaults to `None`.
|
2019-10-27 15:14:52 -04:00
|
|
|
pub aud: Option<HashSet<String>>,
|
2017-04-12 21:08:07 -04:00
|
|
|
/// If it contains a value, the validation will check that the `iss` 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 iss: Option<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>,
|
2017-10-22 07:20:01 -04:00
|
|
|
/// If it contains a value, the validation will check that the `alg` of the header is contained
|
2017-04-22 02:21:16 -04:00
|
|
|
/// in the ones provided and will error otherwise.
|
|
|
|
///
|
2017-10-22 07:20:01 -04:00
|
|
|
/// Defaults to `vec![Algorithm::HS256]`.
|
|
|
|
pub algorithms: Vec<Algorithm>,
|
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 {
|
|
|
|
let mut validation = Validation::default();
|
|
|
|
validation.algorithms = vec![alg];
|
|
|
|
validation
|
|
|
|
}
|
|
|
|
|
2017-04-12 21:08:07 -04:00
|
|
|
/// Since `aud` can be either a String or an array of String in the JWT spec, this method will take
|
|
|
|
/// care of serializing the value.
|
2017-04-11 01:41:44 -04:00
|
|
|
pub fn set_audience<T: Serialize>(&mut self, audience: &T) {
|
2019-10-27 15:14:52 -04:00
|
|
|
let aud = to_value(audience)
|
|
|
|
.unwrap_or_else(|_| panic!("Failed to_value within set_audience)"));
|
|
|
|
let aud = Validation::convert_aud(&aud)
|
|
|
|
.unwrap_or_else(|_| panic!("Failed convert_aud within set_audience"));
|
|
|
|
self.aud = Some(aud);
|
2017-04-11 01:41:44 -04:00
|
|
|
}
|
2019-10-27 15:14:52 -04:00
|
|
|
|
|
|
|
/// Converts a Value, representing a String or collection of Strings, to a
|
|
|
|
/// HashSet<String>, required for audience membership testing
|
|
|
|
fn convert_aud(aud: &Value) -> Result<HashSet<String>> {
|
|
|
|
let aud_from_claim: Vec<String> = match aud.is_array() {
|
|
|
|
true => from_value(aud.clone()).unwrap(),
|
|
|
|
false => {
|
|
|
|
let aud_str: String = match from_value(aud.clone()) {
|
|
|
|
Ok(val) => val,
|
|
|
|
Err(_) => return Err(new_error(ErrorKind::InvalidAudience)),
|
|
|
|
};
|
|
|
|
vec![aud_str]
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
Ok(aud_from_claim.into_iter().collect())
|
|
|
|
}
|
2017-04-11 01:41:44 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for Validation {
|
|
|
|
fn default() -> Validation {
|
|
|
|
Validation {
|
|
|
|
leeway: 0,
|
|
|
|
|
|
|
|
validate_exp: true,
|
2018-07-25 09:42:00 -04:00
|
|
|
validate_nbf: false,
|
2017-04-11 01:41:44 -04:00
|
|
|
|
|
|
|
iss: None,
|
|
|
|
sub: None,
|
|
|
|
aud: None,
|
2017-04-22 02:21:16 -04:00
|
|
|
|
2017-10-22 07:20:01 -04:00
|
|
|
algorithms: vec![Algorithm::HS256],
|
2017-04-11 01:41:44 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn validate(claims: &Map<String, Value>, options: &Validation) -> Result<()> {
|
2017-06-24 02:15:45 -04:00
|
|
|
let now = Utc::now().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") {
|
|
|
|
if from_value::<i64>(exp.clone())? < now - options.leeway {
|
|
|
|
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") {
|
|
|
|
if from_value::<i64>(nbf.clone())? > now + options.leeway {
|
|
|
|
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_iss) = options.iss {
|
|
|
|
if let Some(iss) = claims.get("iss") {
|
2017-04-11 01:41:44 -04:00
|
|
|
if from_value::<String>(iss.clone())? != *correct_iss {
|
2018-07-25 08:43:58 -04:00
|
|
|
return Err(new_error(ErrorKind::InvalidIssuer));
|
2017-04-11 01:41:44 -04:00
|
|
|
}
|
2018-07-25 09:42:00 -04:00
|
|
|
} else {
|
|
|
|
return Err(new_error(ErrorKind::InvalidIssuer));
|
2017-04-11 01:41:44 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-25 09:42:00 -04:00
|
|
|
if let Some(ref correct_sub) = options.sub {
|
|
|
|
if let Some(sub) = claims.get("sub") {
|
2017-04-11 01:41:44 -04:00
|
|
|
if from_value::<String>(sub.clone())? != *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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-25 09:42:00 -04:00
|
|
|
if let Some(ref correct_aud) = options.aud {
|
|
|
|
if let Some(aud) = claims.get("aud") {
|
2019-10-27 15:14:52 -04:00
|
|
|
let converted_aud = Validation::convert_aud(aud)?;
|
|
|
|
if converted_aud.intersection(correct_aud).count() == 0 {
|
2018-07-25 08:43:58 -04:00
|
|
|
return Err(new_error(ErrorKind::InvalidAudience));
|
2017-04-11 01:41:44 -04: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 {
|
2017-06-24 02:15:45 -04:00
|
|
|
use chrono::Utc;
|
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
|
|
|
|
|
|
|
use super::{validate, Validation};
|
|
|
|
|
2019-07-06 14:36:32 -04:00
|
|
|
use crate::errors::ErrorKind;
|
2017-04-11 01:41:44 -04:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn exp_in_future_ok() {
|
|
|
|
let mut claims = Map::new();
|
2017-06-24 02:15:45 -04:00
|
|
|
claims.insert("exp".to_string(), to_value(Utc::now().timestamp() + 10000).unwrap());
|
2017-04-11 01:41:44 -04:00
|
|
|
let res = validate(&claims, &Validation::default());
|
|
|
|
assert!(res.is_ok());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn exp_in_past_fails() {
|
|
|
|
let mut claims = Map::new();
|
2017-06-24 02:15:45 -04:00
|
|
|
claims.insert("exp".to_string(), to_value(Utc::now().timestamp() - 100000).unwrap());
|
2017-04-11 01:41:44 -04:00
|
|
|
let res = validate(&claims, &Validation::default());
|
|
|
|
assert!(res.is_err());
|
|
|
|
|
|
|
|
match res.unwrap_err().kind() {
|
|
|
|
&ErrorKind::ExpiredSignature => (),
|
|
|
|
_ => assert!(false),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn exp_in_past_but_in_leeway_ok() {
|
|
|
|
let mut claims = Map::new();
|
2017-06-24 02:15:45 -04:00
|
|
|
claims.insert("exp".to_string(), to_value(Utc::now().timestamp() - 500).unwrap());
|
2018-10-28 14:58:35 -04:00
|
|
|
let validation = Validation { leeway: 1000 * 60, ..Default::default() };
|
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();
|
|
|
|
let res = validate(&claims, &Validation::default());
|
|
|
|
assert!(res.is_err());
|
|
|
|
match res.unwrap_err().kind() {
|
|
|
|
&ErrorKind::ExpiredSignature => (),
|
|
|
|
_ => assert!(false),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2017-04-11 01:41:44 -04:00
|
|
|
#[test]
|
|
|
|
fn nbf_in_past_ok() {
|
|
|
|
let mut claims = Map::new();
|
2017-06-24 02:15:45 -04:00
|
|
|
claims.insert("nbf".to_string(), to_value(Utc::now().timestamp() - 10000).unwrap());
|
2018-10-28 14:58:35 -04:00
|
|
|
let validation =
|
|
|
|
Validation { validate_exp: false, validate_nbf: true, ..Validation::default() };
|
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();
|
2017-06-24 02:15:45 -04:00
|
|
|
claims.insert("nbf".to_string(), to_value(Utc::now().timestamp() + 100000).unwrap());
|
2018-10-28 14:58:35 -04:00
|
|
|
let validation =
|
|
|
|
Validation { validate_exp: false, validate_nbf: true, ..Validation::default() };
|
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() {
|
|
|
|
&ErrorKind::ImmatureSignature => (),
|
|
|
|
_ => assert!(false),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn nbf_in_future_but_in_leeway_ok() {
|
|
|
|
let mut claims = Map::new();
|
2017-06-24 02:15:45 -04:00
|
|
|
claims.insert("nbf".to_string(), to_value(Utc::now().timestamp() + 500).unwrap());
|
2017-04-11 01:41:44 -04:00
|
|
|
let validation = Validation {
|
|
|
|
leeway: 1000 * 60,
|
2018-07-25 09:42:00 -04:00
|
|
|
validate_nbf: true,
|
|
|
|
validate_exp: false,
|
2017-04-11 01:41:44 -04:00
|
|
|
..Default::default()
|
|
|
|
};
|
|
|
|
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());
|
|
|
|
let validation = Validation {
|
2018-07-25 09:42:00 -04:00
|
|
|
validate_exp: false,
|
2017-04-11 01:41:44 -04:00
|
|
|
iss: Some("Keats".to_string()),
|
|
|
|
..Default::default()
|
|
|
|
};
|
|
|
|
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());
|
|
|
|
let validation = Validation {
|
2018-07-25 09:42:00 -04:00
|
|
|
validate_exp: false,
|
|
|
|
iss: Some("Keats".to_string()),
|
|
|
|
..Default::default()
|
|
|
|
};
|
|
|
|
let res = validate(&claims, &validation);
|
|
|
|
assert!(res.is_err());
|
|
|
|
|
|
|
|
match res.unwrap_err().kind() {
|
|
|
|
&ErrorKind::InvalidIssuer => (),
|
|
|
|
_ => assert!(false),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn iss_missing_fails() {
|
|
|
|
let claims = Map::new();
|
|
|
|
let validation = Validation {
|
|
|
|
validate_exp: false,
|
2017-04-11 01:41:44 -04:00
|
|
|
iss: Some("Keats".to_string()),
|
|
|
|
..Default::default()
|
|
|
|
};
|
|
|
|
let res = validate(&claims, &validation);
|
|
|
|
assert!(res.is_err());
|
|
|
|
|
|
|
|
match res.unwrap_err().kind() {
|
|
|
|
&ErrorKind::InvalidIssuer => (),
|
|
|
|
_ => assert!(false),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn sub_ok() {
|
|
|
|
let mut claims = Map::new();
|
|
|
|
claims.insert("sub".to_string(), to_value("Keats").unwrap());
|
|
|
|
let validation = Validation {
|
2018-07-25 09:42:00 -04:00
|
|
|
validate_exp: false,
|
2017-04-11 01:41:44 -04:00
|
|
|
sub: Some("Keats".to_string()),
|
|
|
|
..Default::default()
|
|
|
|
};
|
|
|
|
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());
|
|
|
|
let validation = Validation {
|
2018-07-25 09:42:00 -04:00
|
|
|
validate_exp: false,
|
|
|
|
sub: Some("Keats".to_string()),
|
|
|
|
..Default::default()
|
|
|
|
};
|
|
|
|
let res = validate(&claims, &validation);
|
|
|
|
assert!(res.is_err());
|
|
|
|
|
|
|
|
match res.unwrap_err().kind() {
|
|
|
|
&ErrorKind::InvalidSubject => (),
|
|
|
|
_ => assert!(false),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn sub_missing_fails() {
|
|
|
|
let claims = Map::new();
|
|
|
|
let validation = Validation {
|
|
|
|
validate_exp: false,
|
2017-04-11 01:41:44 -04:00
|
|
|
sub: Some("Keats".to_string()),
|
|
|
|
..Default::default()
|
|
|
|
};
|
|
|
|
let res = validate(&claims, &validation);
|
|
|
|
assert!(res.is_err());
|
|
|
|
|
|
|
|
match res.unwrap_err().kind() {
|
|
|
|
&ErrorKind::InvalidSubject => (),
|
|
|
|
_ => assert!(false),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn aud_string_ok() {
|
|
|
|
let mut claims = Map::new();
|
|
|
|
claims.insert("aud".to_string(), to_value("Everyone").unwrap());
|
2018-10-28 14:58:35 -04:00
|
|
|
let mut validation = Validation { validate_exp: false, ..Validation::default() };
|
2017-04-11 01:41:44 -04:00
|
|
|
validation.set_audience(&"Everyone");
|
|
|
|
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());
|
2018-10-28 14:58:35 -04:00
|
|
|
let mut validation = Validation { validate_exp: false, ..Validation::default() };
|
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();
|
|
|
|
claims.insert("aud".to_string(), to_value("Everyone").unwrap());
|
2018-10-28 14:58:35 -04:00
|
|
|
let mut validation = Validation { validate_exp: false, ..Validation::default() };
|
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() {
|
|
|
|
&ErrorKind::InvalidAudience => (),
|
|
|
|
_ => assert!(false),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn aud_correct_type_not_matching_fails() {
|
|
|
|
let mut claims = Map::new();
|
|
|
|
claims.insert("aud".to_string(), to_value("Everyone").unwrap());
|
2018-10-28 14:58:35 -04:00
|
|
|
let mut validation = Validation { validate_exp: false, ..Validation::default() };
|
2018-07-25 09:42:00 -04:00
|
|
|
validation.set_audience(&"None");
|
|
|
|
let res = validate(&claims, &validation);
|
|
|
|
assert!(res.is_err());
|
|
|
|
|
|
|
|
match res.unwrap_err().kind() {
|
|
|
|
&ErrorKind::InvalidAudience => (),
|
|
|
|
_ => assert!(false),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn aud_missing_fails() {
|
|
|
|
let claims = Map::new();
|
2018-10-28 14:58:35 -04:00
|
|
|
let mut validation = Validation { validate_exp: false, ..Validation::default() };
|
2017-04-11 01:41:44 -04:00
|
|
|
validation.set_audience(&"None");
|
|
|
|
let res = validate(&claims, &validation);
|
|
|
|
assert!(res.is_err());
|
|
|
|
|
|
|
|
match res.unwrap_err().kind() {
|
|
|
|
&ErrorKind::InvalidAudience => (),
|
|
|
|
_ => assert!(false),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|