From 4776132e5178100db74b9f7e6b9a7565dc442dce Mon Sep 17 00:00:00 2001 From: Thomas Gideon Date: Mon, 22 Jun 2020 11:52:53 -0400 Subject: [PATCH] Migrated to anyhow and chrono from failure and time crates. --- Cargo.toml | 14 ++++----- examples/custom_claims.rs | 6 +--- examples/custom_headers.rs | 6 +--- src/crypt.rs | 26 ++++++++--------- src/error.rs | 3 -- src/header.rs | 9 +++--- src/lib.rs | 60 ++++++++++++++++---------------------- src/payload.rs | 42 +++++++++++++++----------- 8 files changed, 76 insertions(+), 90 deletions(-) delete mode 100644 src/error.rs diff --git a/Cargo.toml b/Cargo.toml index b4a110c..c2e1879 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,17 +9,17 @@ license = "MIT" name = "medallion" readme = "README.md" repository = "http://github.com/cmdln/medallion" -version = "2.3.1" +version = "2.4.0" +edition = "2018" [badges] [badges.travis-ci] branch = "master" repository = "https://travis-ci.org/cmdln/medallion" [dependencies] -base64 = "~0.10.0" -failure = "~0.1.3" +base64 = "~0.12.2" openssl = "~0.10.15" -serde = "^1.0.80" -serde_derive = "^1.0.80" -serde_json = "^1.0.33" -time = "~0.1.40" +serde = { version = "^1.0.114", features = [ "derive" ] } +serde_json = "^1.0.55" +anyhow = "^1.0.31" +chrono = "~0.4.11" diff --git a/examples/custom_claims.rs b/examples/custom_claims.rs index ce09448..eb50f20 100644 --- a/examples/custom_claims.rs +++ b/examples/custom_claims.rs @@ -1,9 +1,5 @@ -// need this for custom derivation -#[macro_use] -extern crate serde_derive; -extern crate medallion; - use medallion::{Header, Payload, Token}; +use serde::{Deserialize, Serialize}; #[derive(Default, Serialize, Deserialize, PartialEq, Debug)] struct Custom { diff --git a/examples/custom_headers.rs b/examples/custom_headers.rs index b8f2468..c733dcd 100644 --- a/examples/custom_headers.rs +++ b/examples/custom_headers.rs @@ -1,9 +1,5 @@ -// need this for custom derivation -#[macro_use] -extern crate serde_derive; -extern crate medallion; - use medallion::{DefaultPayload, DefaultToken, Header}; +use serde::{Deserialize, Serialize}; #[derive(Default, Serialize, Deserialize, PartialEq, Debug)] struct Custom { diff --git a/src/crypt.rs b/src/crypt.rs index dffbe2a..e9edfce 100644 --- a/src/crypt.rs +++ b/src/crypt.rs @@ -1,5 +1,6 @@ +use super::Result; +use crate::header::Algorithm; use base64::{decode_config, encode_config, URL_SAFE_NO_PAD}; -use header::Algorithm; use openssl::{ hash::MessageDigest, memcmp, @@ -8,8 +9,6 @@ use openssl::{ sign::{Signer, Verifier}, }; -use super::Result; - pub fn sign(data: &str, key: &[u8], algorithm: &Algorithm) -> Result { match *algorithm { Algorithm::HS256 => sign_hmac(data, key, MessageDigest::sha256()), @@ -76,8 +75,7 @@ fn verify_rsa(signature: &str, data: &str, key: &[u8], digest: MessageDigest) -> #[cfg(test)] pub mod tests { use super::{sign, verify}; - use header::Algorithm; - use openssl; + use crate::header::Algorithm; #[test] pub fn sign_data_hmac() { @@ -104,16 +102,16 @@ pub mod tests { &*data, &keypair.private_key_to_pem().unwrap(), &Algorithm::RS256, - ).unwrap(); + ) + .unwrap(); - assert!( - verify( - &sig, - &*data, - &keypair.public_key_to_pem().unwrap(), - &Algorithm::RS256 - ).unwrap() - ); + assert!(verify( + &sig, + &*data, + &keypair.public_key_to_pem().unwrap(), + &Algorithm::RS256 + ) + .unwrap()); } #[test] diff --git a/src/error.rs b/src/error.rs deleted file mode 100644 index b508e3e..0000000 --- a/src/error.rs +++ /dev/null @@ -1,3 +0,0 @@ -use failure::Error; - -pub type Result = std::result::Result; diff --git a/src/header.rs b/src/header.rs index a49942b..ea228bb 100644 --- a/src/header.rs +++ b/src/header.rs @@ -1,8 +1,8 @@ -use base64::{decode_config, encode_config, URL_SAFE_NO_PAD}; -use serde::{de::DeserializeOwned, Serialize}; -use serde_json::{self, Value}; - use super::Result; +use anyhow::format_err; +use base64::{decode_config, encode_config, URL_SAFE_NO_PAD}; +use serde::{de::DeserializeOwned, Deserialize, Serialize}; +use serde_json::{self, Value}; /// An extensible Header that provides only algorithm field and allows for additional fields to be /// passed in via a struct that can be serialized and deserialized. Unlike the Claims struct, there @@ -79,6 +79,7 @@ impl Default for Header { #[cfg(test)] mod tests { use super::{Algorithm, Header}; + use serde::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize, PartialEq)] struct CustomHeaders { diff --git a/src/lib.rs b/src/lib.rs index 4ca05ce..ac97b30 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,26 +6,15 @@ ///! ///! Tries to support the standard uses for JWTs while providing reasonable ways to extend, ///! primarily by adding custom headers and claims to tokens. -extern crate base64; -#[macro_use] -extern crate failure; -extern crate openssl; -extern crate serde; -#[macro_use] -extern crate serde_derive; -extern crate serde_json; -extern crate time; - pub use header::{Algorithm, Header}; pub use payload::{DefaultPayload, Payload}; use serde::{de::DeserializeOwned, Serialize}; mod crypt; -mod error; mod header; mod payload; -pub use error::Result; +pub use anyhow::Result; /// A convenient type that binds the same type parameter for the custom claims, an empty tuple, as /// `DefaultPayload` so that the two aliases may be used together to reduce boilerplate when no @@ -104,10 +93,10 @@ where #[cfg(test)] mod tests { use super::Algorithm::{HS256, RS512}; - use openssl; - use std::default::Default; - use time::{self, Duration, Tm}; - use {DefaultPayload, DefaultToken, Header, Payload, Token}; + use crate::{DefaultPayload, DefaultToken, Header, Payload, Token}; + use anyhow::Result; + use chrono::{prelude::*, Duration}; + use std::convert::TryInto; #[test] pub fn raw_data() { @@ -122,11 +111,11 @@ mod tests { #[test] pub fn roundtrip_hmac() { - let now = time::now(); + let now = Utc::now(); let header: Header<()> = Header::default(); let payload = DefaultPayload { - nbf: Some(now.to_timespec().sec as u64), - exp: Some((now + Duration::minutes(5)).to_timespec().sec as u64), + nbf: Some(now.timestamp().try_into().unwrap()), + exp: Some((now + Duration::minutes(5)).timestamp().try_into().unwrap()), ..DefaultPayload::default() }; let token = Token::new(header, payload); @@ -139,27 +128,29 @@ mod tests { } #[test] - pub fn roundtrip_expired() { - let now = time::now(); - let token = create_for_range(now, now + Duration::minutes(-5)); + pub fn roundtrip_expired() -> Result<()> { + let now = Utc::now(); + let token = create_for_range(now, now + Duration::minutes(-5))?; let key = b"secret"; - let raw = token.sign(key).unwrap(); + let raw = token.sign(key)?; let same = Token::parse(&*raw).unwrap(); assert_eq!(token, same); assert_eq!(false, same.verify(key).unwrap()); + Ok(()) } #[test] - pub fn roundtrip_not_yet_valid() { - let now = time::now(); - let token = create_for_range(now + Duration::minutes(5), now + Duration::minutes(10)); + pub fn roundtrip_not_yet_valid() -> Result<()> { + let now = Utc::now(); + let token = create_for_range(now + Duration::minutes(5), now + Duration::minutes(10))?; let key = b"secret"; - let raw = token.sign(key).unwrap(); + let raw = token.sign(key)?; let same = Token::parse(&*raw).unwrap(); assert_eq!(token, same); assert_eq!(false, same.verify(key).unwrap()); + Ok(()) } #[test] @@ -179,19 +170,18 @@ mod tests { let same = Token::parse(&*raw).unwrap(); assert_eq!(token, same); - assert!( - same.verify(&rsa_keypair.public_key_to_pem().unwrap()) - .unwrap() - ); + assert!(same + .verify(&rsa_keypair.public_key_to_pem().unwrap()) + .unwrap()); } - fn create_for_range(nbf: Tm, exp: Tm) -> Token { + fn create_for_range(nbf: DateTime, exp: DateTime) -> Result { let header: Header = Header::default(); let payload = Payload { - nbf: Some(nbf.to_timespec().sec as u64), - exp: Some(exp.to_timespec().sec as u64), + nbf: Some(nbf.timestamp().try_into()?), + exp: Some(exp.timestamp().try_into()?), ..Payload::default() }; - Token::new(header, payload) + Ok(Token::new(header, payload)) } } diff --git a/src/payload.rs b/src/payload.rs index dfaf181..2d6cd83 100644 --- a/src/payload.rs +++ b/src/payload.rs @@ -1,10 +1,9 @@ use super::Result; +use anyhow::format_err; use base64::{decode_config, encode_config, URL_SAFE_NO_PAD}; -use serde::de::DeserializeOwned; -use serde::Serialize; -use serde_json; +use chrono::{DateTime, NaiveDateTime, Utc}; +use serde::{de::DeserializeOwned, Deserialize, Serialize}; use serde_json::value::Value; -use time::{self, Timespec}; /// A default claim set, including the standard, or registered, claims and the ability to specify /// your own as custom claims. @@ -73,7 +72,7 @@ impl Payload { None => { let s = serde_json::to_string(&claims_map)?; let enc = encode_config((&*s).as_bytes(), URL_SAFE_NO_PAD); - return Ok(enc); + Ok(enc) } } } else { @@ -82,13 +81,25 @@ impl Payload { } pub fn verify(&self) -> bool { - let now = time::now().to_timespec(); + let now = Utc::now(); let nbf_verified = match self.nbf { - Some(nbf_sec) => Timespec::new(nbf_sec as i64, 0) < now, + Some(nbf_sec) => { + let nbf = DateTime::::from_utc( + NaiveDateTime::from_timestamp(nbf_sec as i64, 0), + Utc, + ); + nbf < now + } None => true, }; let exp_verified = match self.exp { - Some(exp_sec) => now < Timespec::new(exp_sec as i64, 0), + Some(exp_sec) => { + let exp = DateTime::::from_utc( + NaiveDateTime::from_timestamp(exp_sec as i64, 0), + Utc, + ); + now < exp + } None => true, }; nbf_verified && exp_verified @@ -98,8 +109,9 @@ impl Payload { #[cfg(test)] mod tests { use super::{DefaultPayload, Payload}; + use chrono::{prelude::*, Duration}; + use serde::{Deserialize, Serialize}; use std::default::Default; - use time::{self, Duration}; #[derive(Default, Debug, Serialize, Deserialize, PartialEq)] struct CustomClaims { @@ -199,7 +211,7 @@ mod tests { } fn create_with_nbf(offset: i64) -> DefaultPayload { - let nbf = (time::now() - Duration::minutes(offset)).to_timespec().sec; + let nbf = (Utc::now() - Duration::minutes(offset)).timestamp(); DefaultPayload { nbf: Some(nbf as u64), ..Default::default() @@ -207,7 +219,7 @@ mod tests { } fn create_with_exp(offset: i64) -> DefaultPayload { - let exp = (time::now() + Duration::minutes(offset)).to_timespec().sec; + let exp = (Utc::now() + Duration::minutes(offset)).timestamp(); DefaultPayload { exp: Some(exp as u64), ..Default::default() @@ -215,12 +227,8 @@ mod tests { } fn create_with_nbf_exp(nbf_offset: i64, exp_offset: i64) -> DefaultPayload { - let nbf = (time::now() - Duration::minutes(nbf_offset)) - .to_timespec() - .sec; - let exp = (time::now() + Duration::minutes(exp_offset)) - .to_timespec() - .sec; + let nbf = (Utc::now() - Duration::minutes(nbf_offset)).timestamp(); + let exp = (Utc::now() + Duration::minutes(exp_offset)).timestamp(); DefaultPayload { nbf: Some(nbf as u64), exp: Some(exp as u64),