Unify various decode into the validation struct (#199)

This commit is contained in:
Vincent Prouillet 2021-09-28 10:04:51 +02:00
parent 6a7eec9030
commit 1dcfda92f0
7 changed files with 155 additions and 231 deletions

View File

@ -8,6 +8,7 @@
- Remove deprecated `dangerous_unsafe_decode`
- `Validation::iss` is now a `HashSet` instead of a single value
- `decode` will now error if `Validation::algorithms` is empty
- Add JWKs types for easy interop with various Oauth providers
## 7.2.0 (2020-06-30)

View File

@ -1,5 +1,5 @@
use chrono::prelude::*;
use jsonwebtoken::{DecodingKey, EncodingKey, Header, Validation};
use jsonwebtoken::{Algorithm, DecodingKey, EncodingKey, Header, Validation};
use serde::{Deserialize, Serialize};
const SECRET: &str = "some-secret";
@ -56,7 +56,9 @@ mod jwt_numeric_date {
use super::super::{Claims, SECRET};
use chrono::{Duration, TimeZone, Utc};
use jsonwebtoken::{decode, encode, DecodingKey, EncodingKey, Header, Validation};
use jsonwebtoken::{
decode, encode, Algorithm, DecodingKey, EncodingKey, Header, Validation,
};
#[test]
fn round_trip() {
@ -75,7 +77,7 @@ mod jwt_numeric_date {
let decoded = decode::<Claims>(
&token,
&DecodingKey::from_secret(SECRET.as_ref()),
&Validation::default(),
&Validation::new(Algorithm::HS256),
)
.expect("Failed to decode token");
@ -90,7 +92,7 @@ mod jwt_numeric_date {
let decode_result = decode::<Claims>(
&overflow_token,
&DecodingKey::from_secret(SECRET.as_ref()),
&Validation::default(),
&Validation::new(Algorithm::HS256),
);
assert!(decode_result.is_err());
@ -111,7 +113,7 @@ mod jwt_numeric_date {
let decoded = decode::<Claims>(
&token,
&DecodingKey::from_secret(SECRET.as_ref()),
&Validation::default(),
&Validation::new(Algorithm::HS256),
)
.expect("Failed to decode token")
.claims;
@ -139,7 +141,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let token_data = jsonwebtoken::decode::<Claims>(
&token,
&DecodingKey::from_secret(SECRET.as_ref()),
&Validation::default(),
&Validation::new(Algorithm::HS256),
)?;
println!("token data:\n{:#?}", &token_data);

View File

@ -1,5 +1,5 @@
use jsonwebtoken::errors::ErrorKind;
use jsonwebtoken::{decode, encode, DecodingKey, EncodingKey, Header, Validation};
use jsonwebtoken::{decode, encode, Algorithm, DecodingKey, EncodingKey, Header, Validation};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
@ -18,7 +18,8 @@ fn main() {
Err(_) => panic!(), // in practice you would return the error
};
let validation = Validation { sub: Some("b@b.com".to_string()), ..Validation::default() };
let mut validation = Validation::new(Algorithm::HS256);
validation.sub = Some("b@b.com".to_string());
let token_data = match decode::<Claims>(&token, &DecodingKey::from_secret(key), &validation) {
Ok(c) => c,
Err(err) => match *err.kind() {

View File

@ -140,26 +140,20 @@ impl DecodingKey {
/// Verify signature of a JWT, and return header object and raw payload
///
/// If the token or its signature is invalid, it will return an error.
///
/// ```rust///
/// use jsonwebtoken::{verify_signature, DecodingKey, Validation, Algorithm};
///
///
/// let token = "a.jwt.token".to_string();
/// let token_message = verify_signature(&token, &DecodingKey::from_secret("secret".as_ref()), &Validation::new(Algorithm::HS256));
/// ```
pub fn verify_signature<'a>(
fn verify_signature<'a>(
token: &'a str,
key: &DecodingKey,
validation: &Validation,
) -> Result<(Header, &'a str)> {
if validation.algorithms.is_empty() {
if validation.validate_signature && validation.algorithms.is_empty() {
return Err(new_error(ErrorKind::MissingAlgorithm));
}
for alg in &validation.algorithms {
if key.family != alg.family() {
return Err(new_error(ErrorKind::InvalidAlgorithm));
if validation.validate_signature {
for alg in &validation.algorithms {
if key.family != alg.family() {
return Err(new_error(ErrorKind::InvalidAlgorithm));
}
}
}
@ -167,11 +161,11 @@ pub fn verify_signature<'a>(
let (payload, header) = expect_two!(message.rsplitn(2, '.'));
let header = Header::from_encoded(header)?;
if !validation.algorithms.contains(&header.alg) {
if validation.validate_signature && !validation.algorithms.contains(&header.alg) {
return Err(new_error(ErrorKind::InvalidAlgorithm));
}
if !verify(signature, message.as_bytes(), key, header.alg)? {
if validation.validate_signature && !verify(signature, message.as_bytes(), key, header.alg)? {
return Err(new_error(ErrorKind::InvalidSignature));
}
@ -212,72 +206,6 @@ pub fn decode<T: DeserializeOwned>(
}
}
/// Decode a JWT without any signature verification/validations.
///
/// NOTE: Do not use this unless you know what you are doing! If the token's signature is invalid, it will *not* return an error.
///
/// ```rust
/// use serde::{Deserialize, Serialize};
/// use jsonwebtoken::{dangerous_insecure_decode, Validation, Algorithm};
///
/// #[derive(Debug, Serialize, Deserialize)]
/// struct Claims {
/// sub: String,
/// company: String
/// }
///
/// let token = "a.jwt.token".to_string();
/// // Claims is a struct that implements Deserialize
/// let token_message = dangerous_insecure_decode::<Claims>(&token);
/// ```
pub fn dangerous_insecure_decode<T: DeserializeOwned>(token: &str) -> Result<TokenData<T>> {
let (_, message) = expect_two!(token.rsplitn(2, '.'));
let (claims, header) = expect_two!(message.rsplitn(2, '.'));
let header = Header::from_encoded(header)?;
let (decoded_claims, _): (T, _) = from_jwt_part_claims(claims)?;
Ok(TokenData { header, claims: decoded_claims })
}
/// Decode and validate a JWT without any signature verification.
///
/// If the token is invalid or the claims fail validation, it will return an error.
///
/// NOTE: Do not use this unless you know what you are doing! If the token's signature is invalid, it will *not* return an error.
///
/// ```rust
/// use serde::{Deserialize, Serialize};
/// use jsonwebtoken::{dangerous_insecure_decode_with_validation, Validation, Algorithm};
///
/// #[derive(Debug, Serialize, Deserialize)]
/// struct Claims {
/// sub: String,
/// company: String
/// }
///
/// let token = "a.jwt.token";
/// // Claims is a struct that implements Deserialize
/// let token_message = dangerous_insecure_decode_with_validation::<Claims>(&token, &Validation::new(Algorithm::HS256));
/// ```
pub fn dangerous_insecure_decode_with_validation<T: DeserializeOwned>(
token: &str,
validation: &Validation,
) -> Result<TokenData<T>> {
let (_, message) = expect_two!(token.rsplitn(2, '.'));
let (claims, header) = expect_two!(message.rsplitn(2, '.'));
let header = Header::from_encoded(header)?;
if !validation.algorithms.contains(&header.alg) {
return Err(new_error(ErrorKind::InvalidAlgorithm));
}
let (decoded_claims, claims_map): (T, _) = from_jwt_part_claims(claims)?;
validate(&claims_map, validation)?;
Ok(TokenData { header, claims: decoded_claims })
}
/// Decode a JWT without any signature verification/validations and return its [Header](struct.Header.html).
///
/// If the token has an invalid format (ie 3 parts separated by a `.`), it will return an error.

View File

@ -17,10 +17,7 @@ mod serialization;
mod validation;
pub use algorithms::Algorithm;
pub use decoding::{
dangerous_insecure_decode, dangerous_insecure_decode_with_validation, decode, decode_header,
verify_signature, DecodingKey, TokenData,
};
pub use decoding::{decode, decode_header, DecodingKey, TokenData};
pub use encoding::{encode, EncodingKey};
pub use header::Header;
pub use validation::{get_current_timestamp, Validation};

View File

@ -12,18 +12,16 @@ use crate::errors::{new_error, ErrorKind, Result};
/// All time validation happen on UTC timestamps as seconds.
///
/// ```rust
/// use jsonwebtoken::Validation;
///
/// // Default value
/// let validation = Validation::default();
///
/// // Changing one parameter
/// let mut validation = Validation {leeway: 60, ..Default::default()};
/// use jsonwebtoken::{Validation, Algorithm};
///
/// let mut validation = Validation::new(Algorithm::HS256);
/// validation.leeway = 5;
/// // Setting audience
/// let mut validation = Validation::default();
/// validation.set_audience(&["Me"]); // a single string
/// validation.set_audience(&["Me", "You"]); // array of strings
/// // or issuer
/// validation.set_iss(&["Me"]); // a single string
/// validation.set_iss(&["Me", "You"]); // array of strings
/// ```
#[derive(Debug, Clone, PartialEq)]
pub struct Validation {
@ -64,12 +62,27 @@ pub struct Validation {
///
/// Defaults to `vec![Algorithm::HS256]`.
pub algorithms: Vec<Algorithm>,
/// Whether to validate the JWT signature. Very insecure to turn that off
pub(crate) validate_signature: bool,
}
impl Validation {
/// Create a default validation setup allowing the given alg
pub fn new(alg: Algorithm) -> Validation {
Validation { algorithms: vec![alg], ..Default::default() }
Validation {
algorithms: vec![alg],
leeway: 0,
validate_exp: true,
validate_nbf: false,
iss: None,
sub: None,
aud: None,
validate_signature: true,
}
}
/// `aud` is a collection of one or more acceptable audience members
@ -81,22 +94,12 @@ impl Validation {
pub fn set_iss<T: ToString>(&mut self, items: &[T]) {
self.iss = Some(items.iter().map(|x| x.to_string()).collect())
}
}
impl Default for Validation {
fn default() -> Validation {
Validation {
leeway: 0,
validate_exp: true,
validate_nbf: false,
iss: None,
sub: None,
aud: None,
algorithms: vec![Algorithm::HS256],
}
/// 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;
}
}
@ -190,12 +193,13 @@ mod tests {
use super::{get_current_timestamp, validate, Validation};
use crate::errors::ErrorKind;
use crate::Algorithm;
#[test]
fn exp_in_future_ok() {
let mut claims = Map::new();
claims.insert("exp".to_string(), to_value(get_current_timestamp() + 10000).unwrap());
let res = validate(&claims, &Validation::default());
let res = validate(&claims, &Validation::new(Algorithm::HS256));
assert!(res.is_ok());
}
@ -203,7 +207,7 @@ mod tests {
fn exp_in_past_fails() {
let mut claims = Map::new();
claims.insert("exp".to_string(), to_value(get_current_timestamp() - 100000).unwrap());
let res = validate(&claims, &Validation::default());
let res = validate(&claims, &Validation::new(Algorithm::HS256));
assert!(res.is_err());
match res.unwrap_err().kind() {
@ -216,7 +220,8 @@ mod tests {
fn exp_in_past_but_in_leeway_ok() {
let mut claims = Map::new();
claims.insert("exp".to_string(), to_value(get_current_timestamp() - 500).unwrap());
let validation = Validation { leeway: 1000 * 60, ..Default::default() };
let mut validation = Validation::new(Algorithm::HS256);
validation.leeway = 1000 * 60;
let res = validate(&claims, &validation);
assert!(res.is_ok());
}
@ -225,7 +230,7 @@ mod tests {
#[test]
fn validation_called_even_if_field_is_empty() {
let claims = Map::new();
let res = validate(&claims, &Validation::default());
let res = validate(&claims, &Validation::new(Algorithm::HS256));
assert!(res.is_err());
match res.unwrap_err().kind() {
ErrorKind::ExpiredSignature => (),
@ -237,8 +242,9 @@ mod tests {
fn nbf_in_past_ok() {
let mut claims = Map::new();
claims.insert("nbf".to_string(), to_value(get_current_timestamp() - 10000).unwrap());
let validation =
Validation { validate_exp: false, validate_nbf: true, ..Validation::default() };
let mut validation = Validation::new(Algorithm::HS256);
validation.validate_exp = false;
validation.validate_nbf = true;
let res = validate(&claims, &validation);
assert!(res.is_ok());
}
@ -247,8 +253,9 @@ mod tests {
fn nbf_in_future_fails() {
let mut claims = Map::new();
claims.insert("nbf".to_string(), to_value(get_current_timestamp() + 100000).unwrap());
let validation =
Validation { validate_exp: false, validate_nbf: true, ..Validation::default() };
let mut validation = Validation::new(Algorithm::HS256);
validation.validate_exp = false;
validation.validate_nbf = true;
let res = validate(&claims, &validation);
assert!(res.is_err());
@ -262,12 +269,10 @@ mod tests {
fn nbf_in_future_but_in_leeway_ok() {
let mut claims = Map::new();
claims.insert("nbf".to_string(), to_value(get_current_timestamp() + 500).unwrap());
let validation = Validation {
leeway: 1000 * 60,
validate_nbf: true,
validate_exp: false,
..Default::default()
};
let mut validation = Validation::new(Algorithm::HS256);
validation.validate_exp = false;
validation.validate_nbf = true;
validation.leeway = 1000 * 60;
let res = validate(&claims, &validation);
assert!(res.is_ok());
}
@ -277,10 +282,9 @@ mod tests {
let mut claims = Map::new();
claims.insert("iss".to_string(), to_value("Keats").unwrap());
let mut iss = std::collections::HashSet::new();
iss.insert("Keats".to_string());
let validation = Validation { validate_exp: false, iss: Some(iss), ..Default::default() };
let mut validation = Validation::new(Algorithm::HS256);
validation.validate_exp = false;
validation.set_iss(&["Keats"]);
let res = validate(&claims, &validation);
assert!(res.is_ok());
}
@ -290,10 +294,9 @@ mod tests {
let mut claims = Map::new();
claims.insert("iss".to_string(), to_value("Hacked").unwrap());
let mut iss = std::collections::HashSet::new();
iss.insert("Keats".to_string());
let validation = Validation { validate_exp: false, iss: Some(iss), ..Default::default() };
let mut validation = Validation::new(Algorithm::HS256);
validation.validate_exp = false;
validation.set_iss(&["Keats"]);
let res = validate(&claims, &validation);
assert!(res.is_err());
@ -307,10 +310,9 @@ mod tests {
fn iss_missing_fails() {
let claims = Map::new();
let mut iss = std::collections::HashSet::new();
iss.insert("Keats".to_string());
let validation = Validation { validate_exp: false, iss: Some(iss), ..Default::default() };
let mut validation = Validation::new(Algorithm::HS256);
validation.validate_exp = false;
validation.set_iss(&["Keats"]);
let res = validate(&claims, &validation);
assert!(res.is_err());
@ -324,11 +326,10 @@ mod tests {
fn sub_ok() {
let mut claims = Map::new();
claims.insert("sub".to_string(), to_value("Keats").unwrap());
let validation = Validation {
validate_exp: false,
sub: Some("Keats".to_string()),
..Default::default()
};
let mut validation = Validation::new(Algorithm::HS256);
validation.validate_exp = false;
validation.sub = Some("Keats".to_owned());
let res = validate(&claims, &validation);
assert!(res.is_ok());
}
@ -337,11 +338,10 @@ mod tests {
fn sub_not_matching_fails() {
let mut claims = Map::new();
claims.insert("sub".to_string(), to_value("Hacked").unwrap());
let validation = Validation {
validate_exp: false,
sub: Some("Keats".to_string()),
..Default::default()
};
let mut validation = Validation::new(Algorithm::HS256);
validation.validate_exp = false;
validation.sub = Some("Keats".to_owned());
let res = validate(&claims, &validation);
assert!(res.is_err());
@ -354,11 +354,10 @@ mod tests {
#[test]
fn sub_missing_fails() {
let claims = Map::new();
let validation = Validation {
validate_exp: false,
sub: Some("Keats".to_string()),
..Default::default()
};
let mut validation = Validation::new(Algorithm::HS256);
validation.validate_exp = false;
validation.sub = Some("Keats".to_owned());
let res = validate(&claims, &validation);
assert!(res.is_err());
@ -372,7 +371,8 @@ mod tests {
fn aud_string_ok() {
let mut claims = Map::new();
claims.insert("aud".to_string(), to_value(["Everyone"]).unwrap());
let mut validation = Validation { validate_exp: false, ..Validation::default() };
let mut validation = Validation::new(Algorithm::HS256);
validation.validate_exp = false;
validation.set_audience(&["Everyone"]);
let res = validate(&claims, &validation);
assert!(res.is_ok());
@ -382,7 +382,8 @@ mod tests {
fn aud_array_of_string_ok() {
let mut claims = Map::new();
claims.insert("aud".to_string(), to_value(["UserA", "UserB"]).unwrap());
let mut validation = Validation { validate_exp: false, ..Validation::default() };
let mut validation = Validation::new(Algorithm::HS256);
validation.validate_exp = false;
validation.set_audience(&["UserA", "UserB"]);
let res = validate(&claims, &validation);
assert!(res.is_ok());
@ -392,7 +393,8 @@ mod tests {
fn aud_type_mismatch_fails() {
let mut claims = Map::new();
claims.insert("aud".to_string(), to_value(["Everyone"]).unwrap());
let mut validation = Validation { validate_exp: false, ..Validation::default() };
let mut validation = Validation::new(Algorithm::HS256);
validation.validate_exp = false;
validation.set_audience(&["UserA", "UserB"]);
let res = validate(&claims, &validation);
assert!(res.is_err());
@ -407,7 +409,8 @@ mod tests {
fn aud_correct_type_not_matching_fails() {
let mut claims = Map::new();
claims.insert("aud".to_string(), to_value(["Everyone"]).unwrap());
let mut validation = Validation { validate_exp: false, ..Validation::default() };
let mut validation = Validation::new(Algorithm::HS256);
validation.validate_exp = false;
validation.set_audience(&["None"]);
let res = validate(&claims, &validation);
assert!(res.is_err());
@ -421,7 +424,8 @@ mod tests {
#[test]
fn aud_missing_fails() {
let claims = Map::new();
let mut validation = Validation { validate_exp: false, ..Validation::default() };
let mut validation = Validation::new(Algorithm::HS256);
validation.validate_exp = false;
validation.set_audience(&["None"]);
let res = validate(&claims, &validation);
assert!(res.is_err());
@ -434,22 +438,17 @@ 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 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);
let v = Validation {
leeway: 5,
validate_exp: true,
iss: Some(iss),
sub: Some("sub no check".to_string()),
..Validation::default()
};
let res = validate(&claims, &v);
// It errors because it needs to validate iss/sub which are missing
assert!(res.is_err());
match res.unwrap_err().kind() {
@ -470,9 +469,10 @@ mod tests {
let aud = "my-googleclientid1234.apps.googleusercontent.com".to_string();
let mut aud_hashset = std::collections::HashSet::new();
aud_hashset.insert(aud);
let mut validation = Validation::new(Algorithm::HS256);
validation.validate_exp = false;
validation.set_audience(&["my-googleclientid1234.apps.googleusercontent.com"]);
let validation =
Validation { aud: Some(aud_hashset), validate_exp: false, ..Validation::default() };
let res = validate(&claims, &validation);
println!("{:?}", res);
assert!(res.is_ok());

View File

@ -1,9 +1,8 @@
use chrono::Utc;
use jsonwebtoken::dangerous_insecure_decode_with_validation;
use jsonwebtoken::errors::ErrorKind;
use jsonwebtoken::{
crypto::{sign, verify},
dangerous_insecure_decode, decode, decode_header, encode, Algorithm, DecodingKey, EncodingKey,
Header, Validation,
decode, decode_header, encode, Algorithm, DecodingKey, EncodingKey, Header, Validation,
};
use serde::{Deserialize, Serialize};
@ -39,9 +38,12 @@ fn encode_with_custom_header() {
};
let header = Header { kid: Some("kid".to_string()), ..Default::default() };
let token = encode(&header, &my_claims, &EncodingKey::from_secret(b"secret")).unwrap();
let token_data =
decode::<Claims>(&token, &DecodingKey::from_secret(b"secret"), &Validation::default())
.unwrap();
let token_data = decode::<Claims>(
&token,
&DecodingKey::from_secret(b"secret"),
&Validation::new(Algorithm::HS256),
)
.unwrap();
assert_eq!(my_claims, token_data.claims);
assert_eq!("kid", token_data.header.kid.unwrap());
}
@ -55,9 +57,12 @@ fn round_trip_claim() {
};
let token =
encode(&Header::default(), &my_claims, &EncodingKey::from_secret(b"secret")).unwrap();
let token_data =
decode::<Claims>(&token, &DecodingKey::from_secret(b"secret"), &Validation::default())
.unwrap();
let token_data = decode::<Claims>(
&token,
&DecodingKey::from_secret(b"secret"),
&Validation::new(Algorithm::HS256),
)
.unwrap();
assert_eq!(my_claims, token_data.claims);
assert!(token_data.header.kid.is_none());
}
@ -65,8 +70,11 @@ fn round_trip_claim() {
#[test]
fn decode_token() {
let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUiLCJleHAiOjI1MzI1MjQ4OTF9.9r56oF7ZliOBlOAyiOFperTGxBtPykRQiWNFxhDCW98";
let claims =
decode::<Claims>(token, &DecodingKey::from_secret(b"secret"), &Validation::default());
let claims = decode::<Claims>(
token,
&DecodingKey::from_secret(b"secret"),
&Validation::new(Algorithm::HS256),
);
println!("{:?}", claims);
claims.unwrap();
}
@ -75,8 +83,11 @@ fn decode_token() {
#[should_panic(expected = "InvalidToken")]
fn decode_token_missing_parts() {
let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9";
let claims =
decode::<Claims>(token, &DecodingKey::from_secret(b"secret"), &Validation::default());
let claims = decode::<Claims>(
token,
&DecodingKey::from_secret(b"secret"),
&Validation::new(Algorithm::HS256),
);
claims.unwrap();
}
@ -85,8 +96,11 @@ fn decode_token_missing_parts() {
fn decode_token_invalid_signature() {
let token =
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUifQ.wrong";
let claims =
decode::<Claims>(token, &DecodingKey::from_secret(b"secret"), &Validation::default());
let claims = decode::<Claims>(
token,
&DecodingKey::from_secret(b"secret"),
&Validation::new(Algorithm::HS256),
);
claims.unwrap();
}
@ -117,8 +131,11 @@ fn encode_wrong_alg_family() {
#[test]
fn decode_token_with_bytes_secret() {
let token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUiLCJleHAiOjI1MzI1MjQ4OTF9.Hm0yvKH25TavFPz7J_coST9lZFYH1hQo0tvhvImmaks";
let claims =
decode::<Claims>(token, &DecodingKey::from_secret(b"\x01\x02\x03"), &Validation::default());
let claims = decode::<Claims>(
token,
&DecodingKey::from_secret(b"\x01\x02\x03"),
&Validation::new(Algorithm::HS256),
);
assert!(claims.is_ok());
}
@ -131,60 +148,38 @@ fn decode_header_only() {
}
#[test]
fn dangerous_insecure_decode_token() {
fn dangerous_insecure_decode_valid_token() {
let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUiLCJleHAiOjI1MzI1MjQ4OTF9.9r56oF7ZliOBlOAyiOFperTGxBtPykRQiWNFxhDCW98";
let claims = dangerous_insecure_decode::<Claims>(token);
claims.unwrap();
}
#[test]
#[should_panic(expected = "InvalidToken")]
fn dangerous_insecure_decode_token_missing_parts() {
let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9";
let claims = dangerous_insecure_decode::<Claims>(token);
let mut validation = Validation::new(Algorithm::HS256);
validation.insecure_disable_signature_validation();
let claims = decode::<Claims>(token, &DecodingKey::from_secret(&[]), &validation);
claims.unwrap();
}
#[test]
fn dangerous_insecure_decode_token_invalid_signature() {
let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUiLCJleHAiOjI1MzI1MjQ4OTF9.wrong";
let claims = dangerous_insecure_decode::<Claims>(token);
let mut validation = Validation::new(Algorithm::HS256);
validation.insecure_disable_signature_validation();
let claims = decode::<Claims>(token, &DecodingKey::from_secret(&[]), &validation);
claims.unwrap();
}
#[test]
fn dangerous_insecure_decode_token_wrong_algorithm() {
let token = "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUiLCJleHAiOjI1MzI1MjQ4OTF9.fLxey-hxAKX5rNHHIx1_Ch0KmrbiuoakDVbsJjLWrx8fbjKjrPuWMYEJzTU3SBnYgnZokC-wqSdqckXUOunC-g";
let claims = dangerous_insecure_decode::<Claims>(token);
let mut validation = Validation::new(Algorithm::HS256);
validation.insecure_disable_signature_validation();
let claims = decode::<Claims>(token, &DecodingKey::from_secret(&[]), &validation);
claims.unwrap();
}
#[test]
fn dangerous_insecure_decode_token_with_validation() {
let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUiLCJleHAiOjI1MzI1MjQ4OTF9.9r56oF7ZliOBlOAyiOFperTGxBtPykRQiWNFxhDCW98";
let claims = dangerous_insecure_decode_with_validation::<Claims>(token, &Validation::default());
claims.unwrap();
}
#[test]
#[should_panic(expected = "InvalidToken")]
fn dangerous_insecure_decode_token_with_validation_missing_parts() {
let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9";
let claims = dangerous_insecure_decode_with_validation::<Claims>(token, &Validation::default());
claims.unwrap();
}
#[test]
fn dangerous_insecure_decode_token_with_validation_invalid_signature() {
let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUiLCJleHAiOjI1MzI1MjQ4OTF9.wrong";
let claims = dangerous_insecure_decode_with_validation::<Claims>(token, &Validation::default());
claims.unwrap();
}
#[test]
#[should_panic(expected = "InvalidAlgorithm")]
fn dangerous_insecure_decode_token_with_validation_wrong_algorithm() {
let token = "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUiLCJleHAiOjI1MzI1MjQ4OTF9.fLxey-hxAKX5rNHHIx1_Ch0KmrbiuoakDVbsJjLWrx8fbjKjrPuWMYEJzTU3SBnYgnZokC-wqSdqckXUOunC-g";
let claims = dangerous_insecure_decode_with_validation::<Claims>(token, &Validation::default());
claims.unwrap();
let token = "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUiLCJleHAiOjk1MzI1MjQ4OX0.ONtEUTtP1QmyksYH9ijtPCaXoHjZVHcHKZGX1DuJyPiSyKlT93Y-oKgrp_OSkHSu4huxCcVObLzwsdwF-xwiAQ";
let mut validation = Validation::new(Algorithm::HS256);
validation.insecure_disable_signature_validation();
let claims = decode::<Claims>(token, &DecodingKey::from_secret(&[]), &validation);
let err = claims.unwrap_err();
assert_eq!(err.kind(), &ErrorKind::ExpiredSignature);
}