From 716fe8b64d2b89811e079dc10b7a7bb32a898e08 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 13 Jan 2019 00:20:34 +0000 Subject: [PATCH 1/5] Upgraded ring to 0.14 --- Cargo.toml | 2 +- src/crypto.rs | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c9c2e31..bfd72a6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ keywords = ["jwt", "web", "api", "token", "json"] serde_json = "1.0" serde_derive = "1.0" serde = "1.0" -ring = { version = "0.13", features = ["rsa_signing", "dev_urandom_fallback"] } +ring = { version = "0.14", features = ["dev_urandom_fallback"] } base64 = "0.9" untrusted = "0.6" chrono = "0.4" diff --git a/src/crypto.rs b/src/crypto.rs index 207897b..0f9008f 100644 --- a/src/crypto.rs +++ b/src/crypto.rs @@ -66,14 +66,12 @@ fn sign_rsa(alg: Algorithm, key: &[u8], signing_input: &str) -> Result { }; let key_pair = Arc::new( - signature::RSAKeyPair::from_der(untrusted::Input::from(key)) + signature::RsaKeyPair::from_der(untrusted::Input::from(key)) .map_err(|_| ErrorKind::InvalidRsaKey)?, ); - let mut signing_state = - signature::RSASigningState::new(key_pair).map_err(|_| ErrorKind::InvalidRsaKey)?; - let mut signature = vec![0; signing_state.key_pair().public_modulus_len()]; + let mut signature = vec![0; key_pair.public_modulus_len()]; let rng = rand::SystemRandom::new(); - signing_state + key_pair .sign(ring_alg, &rng, signing_input.as_bytes(), &mut signature) .map_err(|_| ErrorKind::InvalidRsaKey)?; @@ -98,7 +96,7 @@ pub fn sign(signing_input: &str, key: &[u8], algorithm: Algorithm) -> Result Date: Fri, 18 Jan 2019 09:31:56 +0200 Subject: [PATCH 2/5] Fix documentation of default values in validation --- src/validation.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/validation.rs b/src/validation.rs index 3684823..a451390 100644 --- a/src/validation.rs +++ b/src/validation.rs @@ -41,13 +41,13 @@ pub struct Validation { /// /// It will return an error if the time in the `iat` field is in the future. /// - /// Defaults to `true`. + /// Defaults to `false`. pub validate_iat: bool, /// Whether to validate the `nbf` field. /// /// It will return an error if the current timestamp is before the time in the `nbf` field. /// - /// Defaults to `true`. + /// Defaults to `false`. pub validate_nbf: bool, /// If it contains a value, the validation will check that the `aud` field is the same as the /// one provided and will error otherwise. From 86ba9d3d5020a0e8a73f70e7f99ceafc22bf244f Mon Sep 17 00:00:00 2001 From: Vincent Prouillet Date: Mon, 4 Feb 2019 18:35:39 +0100 Subject: [PATCH 3/5] Start on v6 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d3a37e4..0e1716a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 6.0.0 (unreleased) + +- + ## 5.0.1 (2018-09-10) - Add implementation of FromStr for Algorithm From 71d5cb19f790975dbf13e2d10c201e95a89fa660 Mon Sep 17 00:00:00 2001 From: Vincent Prouillet Date: Mon, 4 Feb 2019 18:39:46 +0100 Subject: [PATCH 4/5] Update base64 --- CHANGELOG.md | 2 +- Cargo.toml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e1716a..7427b0f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## 6.0.0 (unreleased) -- +- Update Ring to 0.14 ## 5.0.1 (2018-09-10) diff --git a/Cargo.toml b/Cargo.toml index bfd72a6..d3c1d52 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "jsonwebtoken" -version = "5.0.1" +version = "6.0.0" authors = ["Vincent Prouillet "] license = "MIT" readme = "README.md" @@ -14,6 +14,6 @@ serde_json = "1.0" serde_derive = "1.0" serde = "1.0" ring = { version = "0.14", features = ["dev_urandom_fallback"] } -base64 = "0.9" +base64 = "0.10" untrusted = "0.6" chrono = "0.4" From be27206088f0a2ff959bd4bd2edabc97244700b8 Mon Sep 17 00:00:00 2001 From: Vincent Prouillet Date: Mon, 4 Feb 2019 18:44:08 +0100 Subject: [PATCH 5/5] Remove iat validation, it isnt supposed to be done --- CHANGELOG.md | 1 + README.md | 6 ++--- src/errors.rs | 5 ----- src/validation.rs | 56 ----------------------------------------------- 4 files changed, 4 insertions(+), 64 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7427b0f..6076e67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## 6.0.0 (unreleased) - Update Ring to 0.14 +- Remove `iat` check to match the JWT spec ## 5.0.1 (2018-09-10) diff --git a/README.md b/README.md index 4ba0f6b..8cc8f89 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Add the following to Cargo.toml: ```toml -jsonwebtoken = "5" +jsonwebtoken = "6" serde_derive = "1" serde = "1" ``` @@ -72,7 +72,7 @@ let header = decode_header(&token)?; This does not perform any validation on the token. #### Validation -This library validates automatically the `iat`, `exp` and `nbf` claims if present. You can also validate the `sub`, `iss` and `aud` but +This library validates automatically the `exp` and `nbf` claims if present. You can also validate the `sub`, `iss` and `aud` but those require setting the expected value in the `Validation` struct. Since validating time fields is always a bit tricky due to clock skew, @@ -87,7 +87,7 @@ use jsonwebtoken::{Validation, Algorithm}; let validation = Validation::default(); // Quick way to setup a validation where only the algorithm changes let validation = Validation::new(Algorithm::HS512); -// Adding some leeway (in seconds) for iat, exp and nbf checks +// 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()}; diff --git a/src/errors.rs b/src/errors.rs index d450b9a..f9f11a3 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -50,8 +50,6 @@ pub enum ErrorKind { InvalidAudience, /// When a token’s `aud` claim does not match one of the expected audience values InvalidSubject, - /// When a token’s `iat` claim is in the future - InvalidIssuedAt, /// When a token’s nbf claim represents a time in the future ImmatureSignature, /// When the algorithm in the header doesn't match the one passed to `decode` @@ -84,7 +82,6 @@ impl StdError for Error { ErrorKind::InvalidIssuer => "invalid issuer", ErrorKind::InvalidAudience => "invalid audience", ErrorKind::InvalidSubject => "invalid subject", - ErrorKind::InvalidIssuedAt => "invalid issued at", ErrorKind::ImmatureSignature => "immature signature", ErrorKind::InvalidAlgorithm => "algorithms don't match", ErrorKind::Base64(ref err) => err.description(), @@ -103,7 +100,6 @@ impl StdError for Error { ErrorKind::InvalidIssuer => None, ErrorKind::InvalidAudience => None, ErrorKind::InvalidSubject => None, - ErrorKind::InvalidIssuedAt => None, ErrorKind::ImmatureSignature => None, ErrorKind::InvalidAlgorithm => None, ErrorKind::Base64(ref err) => Some(err), @@ -124,7 +120,6 @@ impl fmt::Display for Error { ErrorKind::InvalidIssuer => write!(f, "invalid issuer"), ErrorKind::InvalidAudience => write!(f, "invalid audience"), ErrorKind::InvalidSubject => write!(f, "invalid subject"), - ErrorKind::InvalidIssuedAt => write!(f, "invalid issued at"), ErrorKind::ImmatureSignature => write!(f, "immature signature"), ErrorKind::InvalidAlgorithm => write!(f, "algorithms don't match"), ErrorKind::Base64(ref err) => write!(f, "base64 error: {}", err), diff --git a/src/validation.rs b/src/validation.rs index a451390..293147a 100644 --- a/src/validation.rs +++ b/src/validation.rs @@ -37,12 +37,6 @@ pub struct Validation { /// /// Defaults to `true`. pub validate_exp: bool, - /// Whether to validate the `iat` field. - /// - /// It will return an error if the time in the `iat` field is in the future. - /// - /// Defaults to `false`. - pub validate_iat: bool, /// Whether to validate the `nbf` field. /// /// It will return an error if the current timestamp is before the time in the `nbf` field. @@ -94,7 +88,6 @@ impl Default for Validation { leeway: 0, validate_exp: true, - validate_iat: false, validate_nbf: false, iss: None, @@ -109,16 +102,6 @@ impl Default for Validation { pub fn validate(claims: &Map, options: &Validation) -> Result<()> { let now = Utc::now().timestamp(); - if options.validate_iat { - if let Some(iat) = claims.get("iat") { - if from_value::(iat.clone())? > now + options.leeway { - return Err(new_error(ErrorKind::InvalidIssuedAt)); - } - } else { - return Err(new_error(ErrorKind::InvalidIssuedAt)); - } - } - if options.validate_exp { if let Some(exp) = claims.get("exp") { if from_value::(exp.clone())? < now - options.leeway { @@ -182,45 +165,6 @@ mod tests { use errors::ErrorKind; - #[test] - fn iat_in_past_ok() { - let mut claims = Map::new(); - claims.insert("iat".to_string(), to_value(Utc::now().timestamp() - 10000).unwrap()); - let validation = - Validation { validate_exp: false, validate_iat: true, ..Validation::default() }; - let res = validate(&claims, &validation); - assert!(res.is_ok()); - } - - #[test] - fn iat_in_future_fails() { - let mut claims = Map::new(); - claims.insert("iat".to_string(), to_value(Utc::now().timestamp() + 100000).unwrap()); - let validation = - Validation { validate_exp: false, validate_iat: true, ..Validation::default() }; - let res = validate(&claims, &validation); - assert!(res.is_err()); - - match res.unwrap_err().kind() { - &ErrorKind::InvalidIssuedAt => (), - _ => assert!(false), - }; - } - - #[test] - fn iat_in_future_but_in_leeway_ok() { - let mut claims = Map::new(); - claims.insert("iat".to_string(), to_value(Utc::now().timestamp() + 50).unwrap()); - let validation = Validation { - leeway: 1000 * 60, - validate_iat: true, - validate_exp: false, - ..Default::default() - }; - let res = validate(&claims, &validation); - assert!(res.is_ok()); - } - #[test] fn exp_in_future_ok() { let mut claims = Map::new();