diff --git a/examples/custom_header.rs b/examples/custom_header.rs index 18f3cb81..1c493269 100644 --- a/examples/custom_header.rs +++ b/examples/custom_header.rs @@ -1,7 +1,7 @@ use serde::{Deserialize, Serialize}; use std::collections::HashMap; -use jsonwebtoken::errors::ErrorKind; +use jsonwebtoken::errors::{ErrorKind, FundamentalError}; use jsonwebtoken::{decode, encode, Algorithm, DecodingKey, EncodingKey, Header, Validation}; #[derive(Debug, Serialize, Deserialize)] @@ -39,7 +39,7 @@ fn main() { ) { Ok(c) => c, Err(err) => match *err.kind() { - ErrorKind::InvalidToken => panic!(), // Example on how to handle a specific error + ErrorKind::Fundamental(FundamentalError::InvalidToken) => panic!(), // Example on how to handle a specific error _ => panic!(), }, }; diff --git a/examples/validation.rs b/examples/validation.rs index ffabc6f1..cdcca35e 100644 --- a/examples/validation.rs +++ b/examples/validation.rs @@ -1,4 +1,4 @@ -use jsonwebtoken::errors::ErrorKind; +use jsonwebtoken::errors::{ErrorKind, FundamentalError, ValidationError}; use jsonwebtoken::{decode, encode, Algorithm, DecodingKey, EncodingKey, Header, Validation}; use serde::{Deserialize, Serialize}; @@ -30,8 +30,8 @@ fn main() { let token_data = match decode::(&token, &DecodingKey::from_secret(key), &validation) { Ok(c) => c, Err(err) => match *err.kind() { - ErrorKind::InvalidToken => panic!("Token is invalid"), // Example on how to handle a specific error - ErrorKind::InvalidIssuer => panic!("Issuer is invalid"), // Example on how to handle a specific error + ErrorKind::Fundamental(FundamentalError::InvalidToken) => panic!("Token is invalid"), // Example on how to handle a specific error + ErrorKind::Validation(ValidationError::InvalidIssuer) => panic!("Issuer is invalid"), // Example on how to handle a specific error _ => panic!("Some other errors"), }, }; diff --git a/src/algorithms.rs b/src/algorithms.rs index e162bab2..83ac7f84 100644 --- a/src/algorithms.rs +++ b/src/algorithms.rs @@ -1,4 +1,4 @@ -use crate::errors::{Error, ErrorKind, Result}; +use crate::errors::{Error, ErrorKind, FundamentalError, Result}; use serde::{Deserialize, Serialize}; use std::str::FromStr; @@ -61,7 +61,7 @@ impl FromStr for Algorithm { "PS512" => Ok(Algorithm::PS512), "RS512" => Ok(Algorithm::RS512), "EdDSA" => Ok(Algorithm::EdDSA), - _ => Err(ErrorKind::InvalidAlgorithmName.into()), + _ => Err(ErrorKind::from(FundamentalError::InvalidAlgorithmName).into()), } } } diff --git a/src/crypto/rsa.rs b/src/crypto/rsa.rs index 4c97db3c..3b9bc806 100644 --- a/src/crypto/rsa.rs +++ b/src/crypto/rsa.rs @@ -1,7 +1,7 @@ use ring::{rand, signature}; use crate::algorithms::Algorithm; -use crate::errors::{ErrorKind, Result}; +use crate::errors::{ErrorKind, FundamentalError, Result}; use crate::serialization::{b64_decode, b64_encode}; /// Only used internally when validating RSA, to map from our enum to the Ring param structs. @@ -39,11 +39,13 @@ pub(crate) fn sign( message: &[u8], ) -> Result { let key_pair = signature::RsaKeyPair::from_der(key) - .map_err(|e| ErrorKind::InvalidRsaKey(e.to_string()))?; + .map_err(|e| ErrorKind::Fundamental(FundamentalError::InvalidRsaKey(e.to_string())))?; let mut signature = vec![0; key_pair.public().modulus_len()]; let rng = rand::SystemRandom::new(); - key_pair.sign(alg, &rng, message, &mut signature).map_err(|_| ErrorKind::RsaFailedSigning)?; + key_pair + .sign(alg, &rng, message, &mut signature) + .map_err(|_| ErrorKind::Fundamental(FundamentalError::RsaFailedSigning))?; Ok(b64_encode(signature)) } diff --git a/src/decoding.rs b/src/decoding.rs index 8d87f03d..3900b29b 100644 --- a/src/decoding.rs +++ b/src/decoding.rs @@ -3,7 +3,7 @@ use serde::de::DeserializeOwned; use crate::algorithms::AlgorithmFamily; use crate::crypto::verify; -use crate::errors::{new_error, ErrorKind, Result}; +use crate::errors::{new_error, ErrorKind, FundamentalError, Result, ValidationError}; use crate::header::Header; use crate::jwk::{AlgorithmParameters, Jwk}; #[cfg(feature = "use_pem")] @@ -36,7 +36,7 @@ macro_rules! expect_two { let mut i = $iter; match (i.next(), i.next(), i.next()) { (Some(first), Some(second), None) => (first, second), - _ => return Err(new_error(ErrorKind::InvalidToken)), + _ => return Err(new_error(ErrorKind::from(FundamentalError::InvalidToken))), } }}; } @@ -210,13 +210,13 @@ fn verify_signature<'a>( validation: &Validation, ) -> Result<(Header, &'a str)> { if validation.validate_signature && validation.algorithms.is_empty() { - return Err(new_error(ErrorKind::MissingAlgorithm)); + return Err(new_error(ErrorKind::from(ValidationError::MissingAlgorithm))); } if validation.validate_signature { for alg in &validation.algorithms { if key.family != alg.family() { - return Err(new_error(ErrorKind::InvalidAlgorithm)); + return Err(new_error(ErrorKind::from(ValidationError::InvalidAlgorithm))); } } } @@ -226,11 +226,11 @@ fn verify_signature<'a>( let header = Header::from_encoded(header)?; if validation.validate_signature && !validation.algorithms.contains(&header.alg) { - return Err(new_error(ErrorKind::InvalidAlgorithm)); + return Err(new_error(ErrorKind::from(ValidationError::InvalidAlgorithm))); } if validation.validate_signature && !verify(signature, message.as_bytes(), key, header.alg)? { - return Err(new_error(ErrorKind::InvalidSignature)); + return Err(new_error(ErrorKind::from(ValidationError::InvalidAlgorithm))); } Ok((header, payload)) diff --git a/src/encoding.rs b/src/encoding.rs index 26f5c4c3..ce84efc3 100644 --- a/src/encoding.rs +++ b/src/encoding.rs @@ -3,7 +3,7 @@ use serde::ser::Serialize; use crate::algorithms::AlgorithmFamily; use crate::crypto; -use crate::errors::{new_error, ErrorKind, Result}; +use crate::errors::{new_error, ErrorKind, Result, ValidationError}; use crate::header::Header; #[cfg(feature = "use_pem")] use crate::pem::decoder::PemEncodedKey; @@ -120,7 +120,7 @@ impl EncodingKey { /// ``` pub fn encode(header: &Header, claims: &T, key: &EncodingKey) -> Result { if key.family != header.alg.family() { - return Err(new_error(ErrorKind::InvalidAlgorithm)); + return Err(new_error(ErrorKind::from(ValidationError::InvalidAlgorithm))); } let encoded_header = b64_encode_part(header)?; let encoded_claims = b64_encode_part(claims)?; diff --git a/src/errors.rs b/src/errors.rs index 2edd7df5..fc6d0217 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -35,6 +35,28 @@ impl Error { #[non_exhaustive] #[derive(Clone, Debug)] pub enum ErrorKind { + /// Errors related to malformed tokens or cryptographic key problems. + Fundamental(FundamentalError), + /// Errors that occur when a token fails claim-based validation. + Validation(ValidationError), + /// Errors originating from third-party libraries used for tasks like + /// base64 decoding, JSON serialization, or cryptographic operations. + ThirdParty(ThirdPartyError), +} + +impl From for ErrorKind { + fn from(value: FundamentalError) -> Self { + Self::Fundamental(value) + } +} + +#[non_exhaustive] +#[derive(Clone, Debug)] +/// Errors that indicate a fundamental issue with the JWT or cryptographic key configuration. +/// This enum may grow additional variants, the `#[non_exhaustive]` +/// attribute makes sure clients don't count on exhaustive matching. +/// (Otherwise, adding a new variant could break existing code.) +pub enum FundamentalError { /// When a token doesn't have a valid JWT shape InvalidToken, /// When the signature doesn't match @@ -49,7 +71,19 @@ pub enum ErrorKind { InvalidAlgorithmName, /// When a key is provided with an invalid format InvalidKeyFormat, +} +impl From for ErrorKind { + fn from(value: ValidationError) -> Self { + Self::Validation(value) + } +} + +#[non_exhaustive] +#[derive(Clone, Debug)] +/// Errors which relate to the validation of a JWT's claims (such as expiration, audience, or issuer) +/// and whether they meet the defined criteria. +pub enum ValidationError { // Validation errors /// When a claim required by the validation is not present MissingRequiredClaim(String), @@ -68,7 +102,19 @@ pub enum ErrorKind { InvalidAlgorithm, /// When the Validation struct does not contain at least 1 algorithm MissingAlgorithm, +} +impl From for ErrorKind { + fn from(value: ThirdPartyError) -> Self { + Self::ThirdParty(value) + } +} + +#[non_exhaustive] +#[derive(Clone, Debug)] +/// Errors originating from external libraries/underlying systems +/// used during the JWT encoding or decoding process. +pub enum ThirdPartyError { // 3rd party errors /// An error happened when decoding some base64 text Base64(base64::DecodeError), @@ -83,25 +129,12 @@ pub enum ErrorKind { impl StdError for Error { fn cause(&self) -> Option<&dyn StdError> { match &*self.0 { - ErrorKind::InvalidToken => None, - ErrorKind::InvalidSignature => None, - ErrorKind::InvalidEcdsaKey => None, - ErrorKind::RsaFailedSigning => None, - ErrorKind::InvalidRsaKey(_) => None, - ErrorKind::ExpiredSignature => None, - ErrorKind::MissingAlgorithm => None, - ErrorKind::MissingRequiredClaim(_) => None, - ErrorKind::InvalidIssuer => None, - ErrorKind::InvalidAudience => None, - ErrorKind::InvalidSubject => None, - ErrorKind::ImmatureSignature => None, - ErrorKind::InvalidAlgorithm => None, - ErrorKind::InvalidAlgorithmName => None, - ErrorKind::InvalidKeyFormat => None, - ErrorKind::Base64(err) => Some(err), - ErrorKind::Json(err) => Some(err.as_ref()), - ErrorKind::Utf8(err) => Some(err), - ErrorKind::Crypto(err) => Some(err), + ErrorKind::Fundamental(_) => None, + ErrorKind::Validation(_) => None, + ErrorKind::ThirdParty(ThirdPartyError::Base64(err)) => Some(err), + ErrorKind::ThirdParty(ThirdPartyError::Json(err)) => Some(err.as_ref()), + ErrorKind::ThirdParty(ThirdPartyError::Utf8(err)) => Some(err), + ErrorKind::ThirdParty(ThirdPartyError::Crypto(err)) => Some(err), } } } @@ -109,25 +142,25 @@ impl StdError for Error { impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match &*self.0 { - ErrorKind::InvalidToken - | ErrorKind::InvalidSignature - | ErrorKind::InvalidEcdsaKey - | ErrorKind::ExpiredSignature - | ErrorKind::RsaFailedSigning - | ErrorKind::MissingAlgorithm - | ErrorKind::InvalidIssuer - | ErrorKind::InvalidAudience - | ErrorKind::InvalidSubject - | ErrorKind::ImmatureSignature - | ErrorKind::InvalidAlgorithm - | ErrorKind::InvalidKeyFormat - | ErrorKind::InvalidAlgorithmName => write!(f, "{:?}", self.0), - ErrorKind::MissingRequiredClaim(c) => write!(f, "Missing required claim: {}", c), - ErrorKind::InvalidRsaKey(msg) => write!(f, "RSA key invalid: {}", msg), - ErrorKind::Json(err) => write!(f, "JSON error: {}", err), - ErrorKind::Utf8(err) => write!(f, "UTF-8 error: {}", err), - ErrorKind::Crypto(err) => write!(f, "Crypto error: {}", err), - ErrorKind::Base64(err) => write!(f, "Base64 error: {}", err), + ErrorKind::Fundamental(FundamentalError::InvalidRsaKey(msg)) => { + write!(f, "RSA key invalid: {}", msg) + } + ErrorKind::Validation(ValidationError::MissingRequiredClaim(claim)) => { + write!(f, "Missing required claim: {}", claim) + } + ErrorKind::ThirdParty(ThirdPartyError::Json(err)) => { + write!(f, "JSON error: {}", err) + } + ErrorKind::ThirdParty(ThirdPartyError::Utf8(err)) => { + write!(f, "UTF-8 error: {}", err) + } + ErrorKind::ThirdParty(ThirdPartyError::Crypto(err)) => { + write!(f, "Crypto error: {}", err) + } + ErrorKind::ThirdParty(ThirdPartyError::Base64(err)) => { + write!(f, "Base64 error: {}", err) + } + _ => write!(f, "{:?}", self.0), } } } @@ -143,31 +176,31 @@ impl Eq for ErrorKind {} impl From for Error { fn from(err: base64::DecodeError) -> Error { - new_error(ErrorKind::Base64(err)) + new_error(ErrorKind::ThirdParty(ThirdPartyError::Base64(err))) } } impl From for Error { fn from(err: serde_json::Error) -> Error { - new_error(ErrorKind::Json(Arc::new(err))) + new_error(ErrorKind::ThirdParty(ThirdPartyError::Json(Arc::new(err)))) } } impl From<::std::string::FromUtf8Error> for Error { fn from(err: ::std::string::FromUtf8Error) -> Error { - new_error(ErrorKind::Utf8(err)) + new_error(ErrorKind::ThirdParty(ThirdPartyError::Utf8(err))) } } impl From<::ring::error::Unspecified> for Error { fn from(err: ::ring::error::Unspecified) -> Error { - new_error(ErrorKind::Crypto(err)) + new_error(ErrorKind::ThirdParty(ThirdPartyError::Crypto(err))) } } impl From<::ring::error::KeyRejected> for Error { fn from(_err: ::ring::error::KeyRejected) -> Error { - new_error(ErrorKind::InvalidEcdsaKey) + new_error(ErrorKind::Fundamental(FundamentalError::InvalidEcdsaKey)) } } @@ -188,7 +221,7 @@ mod tests { fn test_error_rendering() { assert_eq!( "InvalidAlgorithmName", - Error::from(ErrorKind::InvalidAlgorithmName).to_string() + Error::from(ErrorKind::Fundamental(FundamentalError::InvalidAlgorithmName)).to_string() ); } } diff --git a/src/jwk.rs b/src/jwk.rs index d1686dab..89243341 100644 --- a/src/jwk.rs +++ b/src/jwk.rs @@ -5,7 +5,7 @@ //! tweaked to remove the private bits as it's not the goal for this crate currently. use crate::{ - errors::{self, Error, ErrorKind}, + errors::{self, Error, ErrorKind, FundamentalError}, Algorithm, }; use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; @@ -209,7 +209,7 @@ impl FromStr for KeyAlgorithm { "RSA1_5" => Ok(KeyAlgorithm::RSA1_5), "RSA-OAEP" => Ok(KeyAlgorithm::RSA_OAEP), "RSA-OAEP-256" => Ok(KeyAlgorithm::RSA_OAEP_256), - _ => Err(ErrorKind::InvalidAlgorithmName.into()), + _ => Err(ErrorKind::from(FundamentalError::InvalidAlgorithmName).into()), } } } diff --git a/src/pem/decoder.rs b/src/pem/decoder.rs index 94ff8821..ff716b06 100644 --- a/src/pem/decoder.rs +++ b/src/pem/decoder.rs @@ -1,4 +1,4 @@ -use crate::errors::{ErrorKind, Result}; +use crate::errors::{ErrorKind, FundamentalError, Result}; /// Supported PEM files for EC and RSA Public and Private Keys #[derive(Debug, PartialEq)] @@ -55,7 +55,11 @@ impl PemEncodedKey { Ok(content) => { let asn1_content = match simple_asn1::from_der(content.contents()) { Ok(asn1) => asn1, - Err(_) => return Err(ErrorKind::InvalidKeyFormat.into()), + Err(_) => { + return Err( + ErrorKind::Fundamental(FundamentalError::InvalidKeyFormat).into() + ) + } }; match content.tag() { @@ -112,25 +116,30 @@ impl PemEncodedKey { standard: Standard::Pkcs8, }) } - None => Err(ErrorKind::InvalidKeyFormat.into()), + None => { + Err(ErrorKind::Fundamental(FundamentalError::InvalidKeyFormat) + .into()) + } } } // Unknown/unsupported type - _ => Err(ErrorKind::InvalidKeyFormat.into()), + _ => Err(ErrorKind::Fundamental(FundamentalError::InvalidKeyFormat).into()), } } - Err(_) => Err(ErrorKind::InvalidKeyFormat.into()), + Err(_) => Err(ErrorKind::Fundamental(FundamentalError::InvalidKeyFormat).into()), } } /// Can only be PKCS8 pub fn as_ec_private_key(&self) -> Result<&[u8]> { match self.standard { - Standard::Pkcs1 => Err(ErrorKind::InvalidKeyFormat.into()), + Standard::Pkcs1 => { + Err(ErrorKind::Fundamental(FundamentalError::InvalidKeyFormat).into()) + } Standard::Pkcs8 => match self.pem_type { PemType::EcPrivate => Ok(self.content.as_slice()), - _ => Err(ErrorKind::InvalidKeyFormat.into()), + _ => Err(ErrorKind::Fundamental(FundamentalError::InvalidKeyFormat).into()), }, } } @@ -138,10 +147,12 @@ impl PemEncodedKey { /// Can only be PKCS8 pub fn as_ec_public_key(&self) -> Result<&[u8]> { match self.standard { - Standard::Pkcs1 => Err(ErrorKind::InvalidKeyFormat.into()), + Standard::Pkcs1 => { + Err(ErrorKind::Fundamental(FundamentalError::InvalidKeyFormat).into()) + } Standard::Pkcs8 => match self.pem_type { PemType::EcPublic => extract_first_bitstring(&self.asn1), - _ => Err(ErrorKind::InvalidKeyFormat.into()), + _ => Err(ErrorKind::Fundamental(FundamentalError::InvalidKeyFormat).into()), }, } } @@ -149,10 +160,12 @@ impl PemEncodedKey { /// Can only be PKCS8 pub fn as_ed_private_key(&self) -> Result<&[u8]> { match self.standard { - Standard::Pkcs1 => Err(ErrorKind::InvalidKeyFormat.into()), + Standard::Pkcs1 => { + Err(ErrorKind::Fundamental(FundamentalError::InvalidKeyFormat).into()) + } Standard::Pkcs8 => match self.pem_type { PemType::EdPrivate => Ok(self.content.as_slice()), - _ => Err(ErrorKind::InvalidKeyFormat.into()), + _ => Err(ErrorKind::Fundamental(FundamentalError::InvalidKeyFormat).into()), }, } } @@ -160,10 +173,12 @@ impl PemEncodedKey { /// Can only be PKCS8 pub fn as_ed_public_key(&self) -> Result<&[u8]> { match self.standard { - Standard::Pkcs1 => Err(ErrorKind::InvalidKeyFormat.into()), + Standard::Pkcs1 => { + Err(ErrorKind::Fundamental(FundamentalError::InvalidKeyFormat).into()) + } Standard::Pkcs8 => match self.pem_type { PemType::EdPublic => extract_first_bitstring(&self.asn1), - _ => Err(ErrorKind::InvalidKeyFormat.into()), + _ => Err(ErrorKind::Fundamental(FundamentalError::InvalidKeyFormat).into()), }, } } @@ -175,7 +190,7 @@ impl PemEncodedKey { Standard::Pkcs8 => match self.pem_type { PemType::RsaPrivate => extract_first_bitstring(&self.asn1), PemType::RsaPublic => extract_first_bitstring(&self.asn1), - _ => Err(ErrorKind::InvalidKeyFormat.into()), + _ => Err(ErrorKind::Fundamental(FundamentalError::InvalidKeyFormat).into()), }, } } @@ -204,7 +219,7 @@ fn extract_first_bitstring(asn1: &[simple_asn1::ASN1Block]) -> Result<&[u8]> { } } - Err(ErrorKind::InvalidEcdsaKey.into()) + Err(ErrorKind::Fundamental(FundamentalError::InvalidEcdsaKey).into()) } /// Find whether this is EC, RSA, or Ed diff --git a/src/validation.rs b/src/validation.rs index bfceded5..29422f34 100644 --- a/src/validation.rs +++ b/src/validation.rs @@ -7,7 +7,7 @@ use serde::de::{self, Visitor}; use serde::{Deserialize, Deserializer}; use crate::algorithms::Algorithm; -use crate::errors::{new_error, ErrorKind, Result}; +use crate::errors::{new_error, ErrorKind, Result, ValidationError}; /// Contains the various validations that are applied after decoding a JWT. /// @@ -264,7 +264,9 @@ pub(crate) fn validate(claims: ClaimsForValidation, options: &Validation) -> Res }; if !present { - return Err(new_error(ErrorKind::MissingRequiredClaim(required_claim.clone()))); + return Err(new_error(ErrorKind::from(ValidationError::MissingRequiredClaim( + required_claim.clone(), + )))); } } @@ -274,30 +276,30 @@ pub(crate) fn validate(claims: ClaimsForValidation, options: &Validation) -> Res if matches!(claims.exp, TryParse::Parsed(exp) if options.validate_exp && exp - options.reject_tokens_expiring_in_less_than < now - options.leeway ) { - return Err(new_error(ErrorKind::ExpiredSignature)); + return Err(new_error(ValidationError::ExpiredSignature.into())); } if matches!(claims.nbf, TryParse::Parsed(nbf) if options.validate_nbf && nbf > now + options.leeway) { - return Err(new_error(ErrorKind::ImmatureSignature)); + return Err(new_error(ValidationError::ImmatureSignature.into())); } } if let (TryParse::Parsed(sub), Some(correct_sub)) = (claims.sub, options.sub.as_deref()) { if sub != correct_sub { - return Err(new_error(ErrorKind::InvalidSubject)); + return Err(new_error(ValidationError::InvalidSubject.into())); } } match (claims.iss, options.iss.as_ref()) { (TryParse::Parsed(Issuer::Single(iss)), Some(correct_iss)) => { if !correct_iss.contains(&*iss) { - return Err(new_error(ErrorKind::InvalidIssuer)); + return Err(new_error(ValidationError::InvalidIssuer.into())); } } (TryParse::Parsed(Issuer::Multiple(iss)), Some(correct_iss)) => { if !is_subset(correct_iss, &iss) { - return Err(new_error(ErrorKind::InvalidIssuer)); + return Err(new_error(ValidationError::InvalidIssuer.into())); } } _ => {} @@ -313,16 +315,16 @@ pub(crate) fn validate(claims: ClaimsForValidation, options: &Validation) -> Res // "aud" claim when this claim is present, then the JWT MUST be // rejected. (TryParse::Parsed(_), None) => { - return Err(new_error(ErrorKind::InvalidAudience)); + return Err(new_error(ValidationError::InvalidAudience.into())); } (TryParse::Parsed(Audience::Single(aud)), Some(correct_aud)) => { if !correct_aud.contains(&*aud) { - return Err(new_error(ErrorKind::InvalidAudience)); + return Err(new_error(ValidationError::InvalidAudience.into())); } } (TryParse::Parsed(Audience::Multiple(aud)), Some(correct_aud)) => { if !is_subset(correct_aud, &aud) { - return Err(new_error(ErrorKind::InvalidAudience)); + return Err(new_error(ValidationError::InvalidAudience.into())); } } _ => {} @@ -376,7 +378,7 @@ mod tests { use super::{get_current_timestamp, validate, ClaimsForValidation, Validation}; - use crate::errors::ErrorKind; + use crate::errors::{ErrorKind, ValidationError}; use crate::Algorithm; use std::collections::HashSet; @@ -430,7 +432,7 @@ mod tests { assert!(res.is_err()); match res.unwrap_err().kind() { - ErrorKind::ExpiredSignature => (), + ErrorKind::Validation(crate::errors::ValidationError::ExpiredSignature) => (), _ => unreachable!(), }; } @@ -443,7 +445,7 @@ mod tests { assert!(res.is_err()); match res.unwrap_err().kind() { - ErrorKind::ExpiredSignature => (), + ErrorKind::Validation(crate::errors::ValidationError::ExpiredSignature) => (), _ => unreachable!(), }; } @@ -467,7 +469,10 @@ mod tests { let mut validation = Validation::new(Algorithm::HS256); validation.set_required_spec_claims(&[spec_claim]); let res = validate(deserialize_claims(&claims), &validation).unwrap_err(); - assert_eq!(res.kind(), &ErrorKind::MissingRequiredClaim(spec_claim.to_owned())); + assert_eq!( + res.kind(), + &ValidationError::MissingRequiredClaim(spec_claim.to_owned()).into() + ); } } @@ -551,7 +556,7 @@ mod tests { assert!(res.is_err()); match res.unwrap_err().kind() { - ErrorKind::ImmatureSignature => (), + ErrorKind::Validation(crate::errors::ValidationError::ImmatureSignature) => (), _ => unreachable!(), }; } @@ -606,7 +611,7 @@ mod tests { assert!(res.is_err()); match res.unwrap_err().kind() { - ErrorKind::InvalidIssuer => (), + ErrorKind::Validation(ValidationError::InvalidIssuer) => (), _ => unreachable!(), }; } @@ -623,7 +628,9 @@ mod tests { let res = validate(deserialize_claims(&claims), &validation); match res.unwrap_err().kind() { - ErrorKind::MissingRequiredClaim(claim) => assert_eq!(claim, "iss"), + ErrorKind::Validation(ValidationError::MissingRequiredClaim(claim)) => { + assert_eq!(claim, "iss") + } _ => unreachable!(), }; } @@ -652,7 +659,7 @@ mod tests { assert!(res.is_err()); match res.unwrap_err().kind() { - ErrorKind::InvalidSubject => (), + ErrorKind::Validation(ValidationError::InvalidSubject) => (), _ => unreachable!(), }; } @@ -669,7 +676,9 @@ mod tests { assert!(res.is_err()); match res.unwrap_err().kind() { - ErrorKind::MissingRequiredClaim(claim) => assert_eq!(claim, "sub"), + ErrorKind::Validation(ValidationError::MissingRequiredClaim(claim)) => { + assert_eq!(claim, "sub") + } _ => unreachable!(), }; } @@ -710,7 +719,7 @@ mod tests { assert!(res.is_err()); match res.unwrap_err().kind() { - ErrorKind::InvalidAudience => (), + ErrorKind::Validation(ValidationError::InvalidAudience) => (), _ => unreachable!(), }; } @@ -727,7 +736,7 @@ mod tests { assert!(res.is_err()); match res.unwrap_err().kind() { - ErrorKind::InvalidAudience => (), + ErrorKind::Validation(ValidationError::InvalidAudience) => (), _ => unreachable!(), }; } @@ -744,7 +753,7 @@ mod tests { assert!(res.is_err()); match res.unwrap_err().kind() { - ErrorKind::InvalidAudience => (), + ErrorKind::Validation(ValidationError::InvalidAudience) => (), _ => unreachable!(), }; } @@ -774,7 +783,9 @@ mod tests { assert!(res.is_err()); match res.unwrap_err().kind() { - ErrorKind::MissingRequiredClaim(claim) => assert_eq!(claim, "aud"), + ErrorKind::Validation(ValidationError::MissingRequiredClaim(claim)) => { + assert_eq!(claim, "aud") + } _ => unreachable!(), }; } @@ -795,7 +806,9 @@ mod tests { // It errors because it needs to validate iss/sub which are missing assert!(res.is_err()); match res.unwrap_err().kind() { - ErrorKind::MissingRequiredClaim(claim) => assert_eq!(claim, "iss"), + ErrorKind::Validation(ValidationError::MissingRequiredClaim(claim)) => { + assert_eq!(claim, "iss") + } t => panic!("{:?}", t), }; } diff --git a/tests/hmac.rs b/tests/hmac.rs index dba0a169..f9c93b67 100644 --- a/tests/hmac.rs +++ b/tests/hmac.rs @@ -1,4 +1,4 @@ -use jsonwebtoken::errors::ErrorKind; +use jsonwebtoken::errors::{ErrorKind, ValidationError}; use jsonwebtoken::jwk::Jwk; use jsonwebtoken::{ crypto::{sign, verify}, @@ -268,7 +268,7 @@ fn dangerous_insecure_decode_token_with_validation_wrong_algorithm() { validation.insecure_disable_signature_validation(); let claims = decode::(token, &DecodingKey::from_secret(&[]), &validation); let err = claims.unwrap_err(); - assert_eq!(err.kind(), &ErrorKind::ExpiredSignature); + assert_eq!(err.kind(), &ErrorKind::Validation(ValidationError::ExpiredSignature)); } #[test]