Reorganise tests

This commit is contained in:
Vincent Prouillet 2019-11-03 15:36:19 +00:00
parent caef740ad4
commit 210e96063d
18 changed files with 193 additions and 194 deletions

View File

@ -8,6 +8,7 @@
- Update to 2018 edition
- Changed aud field type in Validation to `Option<HashSet<String>>`. Audience
validation now tests for "any-of-these" audience membership.
- Add support for keys in PEM format
## 6.0.1 (2019-05-10)

View File

@ -15,7 +15,9 @@ serde_json = "1.0"
serde_derive = "1.0"
serde = "1.0"
ring = { version = "0.16.5", features = ["std"] }
base64 = "0.10"
base64 = "0.11"
# For validation
chrono = "0.4"
# For PEM decoding
pem = "0.7"
simple_asn1 = "0.4.0"
simple_asn1 = "0.4"

View File

@ -56,3 +56,22 @@ impl FromStr for Algorithm {
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn generate_algorithm_enum_from_str() {
assert!(Algorithm::from_str("HS256").is_ok());
assert!(Algorithm::from_str("HS384").is_ok());
assert!(Algorithm::from_str("HS512").is_ok());
assert!(Algorithm::from_str("RS256").is_ok());
assert!(Algorithm::from_str("RS384").is_ok());
assert!(Algorithm::from_str("RS512").is_ok());
assert!(Algorithm::from_str("PS256").is_ok());
assert!(Algorithm::from_str("PS384").is_ok());
assert!(Algorithm::from_str("PS512").is_ok());
assert!(Algorithm::from_str("").is_err());
}
}

View File

@ -403,4 +403,28 @@ mod tests {
_ => assert!(false),
};
}
// https://github.com/Keats/jsonwebtoken/issues/51
#[test]
fn does_validation_in_right_order() {
let mut claims = Map::new();
claims.insert("exp".to_string(), to_value(Utc::now().timestamp() + 10000).unwrap());
let v = Validation {
leeway: 5,
validate_exp: true,
iss: Some("iss no check".to_string()),
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() {
&ErrorKind::InvalidIssuer => (),
t @ _ => {
println!("{:?}", t);
assert!(false)
}
};
}
}

View File

@ -1,10 +1,6 @@
extern crate jsonwebtoken;
#[macro_use]
extern crate serde_derive;
extern crate chrono;
use chrono::Utc;
use jsonwebtoken::{decode, decode_pem, encode, sign, verify, Algorithm, Header, Key, Validation};
use serde_derive::{Deserialize, Serialize};
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
pub struct Claims {
@ -49,10 +45,3 @@ fn round_trip_claim() {
assert_eq!(my_claims, token_data.claims);
assert!(token_data.header.kid.is_none());
}
#[test]
#[should_panic(expected = "InvalidKeyFormat")]
fn fails_with_non_pkcs8_key_format() {
let privkey = include_bytes!("private_rsa_key.der");
let _encrypted = sign("hello world", Key::Der(&privkey[..]), Algorithm::ES256).unwrap();
}

134
tests/hmac.rs Normal file
View File

@ -0,0 +1,134 @@
use chrono::Utc;
use jsonwebtoken::{
dangerous_unsafe_decode, decode, decode_header, encode, sign, verify, Algorithm, Header, Key,
Validation,
};
use serde_derive::{Deserialize, Serialize};
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
pub struct Claims {
sub: String,
company: String,
exp: i64,
}
#[test]
fn sign_hs256() {
let result = sign("hello world", Key::Hmac(b"secret"), Algorithm::HS256).unwrap();
let expected = "c0zGLzKEFWj0VxWuufTXiRMk5tlI5MbGDAYhzaxIYjo";
assert_eq!(result, expected);
}
#[test]
fn verify_hs256() {
let sig = "c0zGLzKEFWj0VxWuufTXiRMk5tlI5MbGDAYhzaxIYjo";
let valid = verify(sig, "hello world", Key::Hmac(b"secret"), Algorithm::HS256).unwrap();
assert!(valid);
}
#[test]
fn encode_with_custom_header() {
let my_claims = Claims {
sub: "b@b.com".to_string(),
company: "ACME".to_string(),
exp: Utc::now().timestamp() + 10000,
};
let mut header = Header::default();
header.kid = Some("kid".to_string());
let token = encode(&header, &my_claims, Key::Hmac(b"secret")).unwrap();
let token_data =
decode::<Claims>(&token, Key::Hmac(b"secret"), &Validation::default()).unwrap();
assert_eq!(my_claims, token_data.claims);
assert_eq!("kid", token_data.header.kid.unwrap());
}
#[test]
fn round_trip_claim() {
let my_claims = Claims {
sub: "b@b.com".to_string(),
company: "ACME".to_string(),
exp: Utc::now().timestamp() + 10000,
};
let token = encode(&Header::default(), &my_claims, Key::Hmac(b"secret")).unwrap();
let token_data =
decode::<Claims>(&token, Key::Hmac(b"secret"), &Validation::default()).unwrap();
assert_eq!(my_claims, token_data.claims);
assert!(token_data.header.kid.is_none());
}
#[test]
fn decode_token() {
let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUiLCJleHAiOjI1MzI1MjQ4OTF9.9r56oF7ZliOBlOAyiOFperTGxBtPykRQiWNFxhDCW98";
let claims = decode::<Claims>(token, Key::Hmac(b"secret"), &Validation::default());
println!("{:?}", claims);
claims.unwrap();
}
#[test]
#[should_panic(expected = "InvalidToken")]
fn decode_token_missing_parts() {
let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9";
let claims = decode::<Claims>(token, Key::Hmac(b"secret"), &Validation::default());
claims.unwrap();
}
#[test]
#[should_panic(expected = "InvalidSignature")]
fn decode_token_invalid_signature() {
let token =
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUifQ.wrong";
let claims = decode::<Claims>(token, Key::Hmac(b"secret"), &Validation::default());
claims.unwrap();
}
#[test]
#[should_panic(expected = "InvalidAlgorithm")]
fn decode_token_wrong_algorithm() {
let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUifQ.I1BvFoHe94AFf09O6tDbcSB8-jp8w6xZqmyHIwPeSdY";
let claims = decode::<Claims>(token, Key::Hmac(b"secret"), &Validation::new(Algorithm::RS512));
claims.unwrap();
}
#[test]
fn decode_token_with_bytes_secret() {
let token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUiLCJleHAiOjI1MzI1MjQ4OTF9.Hm0yvKH25TavFPz7J_coST9lZFYH1hQo0tvhvImmaks";
let claims = decode::<Claims>(token, Key::Hmac(b"\x01\x02\x03"), &Validation::default());
assert!(claims.is_ok());
}
#[test]
fn decode_header_only() {
let token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJjb21wYW55IjoiMTIzNDU2Nzg5MCIsInN1YiI6IkpvaG4gRG9lIn0.S";
let header = decode_header(token).unwrap();
assert_eq!(header.alg, Algorithm::HS256);
assert_eq!(header.typ, Some("JWT".to_string()));
}
#[test]
fn dangerous_unsafe_decode_token() {
let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUiLCJleHAiOjI1MzI1MjQ4OTF9.9r56oF7ZliOBlOAyiOFperTGxBtPykRQiWNFxhDCW98";
let claims = dangerous_unsafe_decode::<Claims>(token);
claims.unwrap();
}
#[test]
#[should_panic(expected = "InvalidToken")]
fn dangerous_unsafe_decode_token_missing_parts() {
let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9";
let claims = dangerous_unsafe_decode::<Claims>(token);
claims.unwrap();
}
#[test]
fn dangerous_unsafe_decode_token_invalid_signature() {
let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUiLCJleHAiOjI1MzI1MjQ4OTF9.wrong";
let claims = dangerous_unsafe_decode::<Claims>(token);
claims.unwrap();
}
#[test]
fn dangerous_unsafe_decode_token_wrong_algorithm() {
let token = "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUiLCJleHAiOjI1MzI1MjQ4OTF9.fLxey-hxAKX5rNHHIx1_Ch0KmrbiuoakDVbsJjLWrx8fbjKjrPuWMYEJzTU3SBnYgnZokC-wqSdqckXUOunC-g";
let claims = dangerous_unsafe_decode::<Claims>(token);
claims.unwrap();
}

View File

@ -1,175 +1,2 @@
extern crate jsonwebtoken;
#[macro_use]
extern crate serde_derive;
extern crate chrono;
use chrono::Utc;
use jsonwebtoken::{
dangerous_unsafe_decode, decode, decode_header, encode, sign, verify, Algorithm, Header, Key,
Validation,
};
use std::str::FromStr;
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
pub struct Claims {
sub: String,
company: String,
exp: i64,
}
#[test]
fn sign_hs256() {
let result = sign("hello world", Key::Hmac(b"secret"), Algorithm::HS256).unwrap();
let expected = "c0zGLzKEFWj0VxWuufTXiRMk5tlI5MbGDAYhzaxIYjo";
assert_eq!(result, expected);
}
#[test]
fn verify_hs256() {
let sig = "c0zGLzKEFWj0VxWuufTXiRMk5tlI5MbGDAYhzaxIYjo";
let valid = verify(sig, "hello world", Key::Hmac(b"secret"), Algorithm::HS256).unwrap();
assert!(valid);
}
#[test]
fn encode_with_custom_header() {
let my_claims = Claims {
sub: "b@b.com".to_string(),
company: "ACME".to_string(),
exp: Utc::now().timestamp() + 10000,
};
let mut header = Header::default();
header.kid = Some("kid".to_string());
let token = encode(&header, &my_claims, Key::Hmac(b"secret")).unwrap();
let token_data =
decode::<Claims>(&token, Key::Hmac(b"secret"), &Validation::default()).unwrap();
assert_eq!(my_claims, token_data.claims);
assert_eq!("kid", token_data.header.kid.unwrap());
}
#[test]
fn round_trip_claim() {
let my_claims = Claims {
sub: "b@b.com".to_string(),
company: "ACME".to_string(),
exp: Utc::now().timestamp() + 10000,
};
let token = encode(&Header::default(), &my_claims, Key::Hmac(b"secret")).unwrap();
let token_data =
decode::<Claims>(&token, Key::Hmac(b"secret"), &Validation::default()).unwrap();
assert_eq!(my_claims, token_data.claims);
assert!(token_data.header.kid.is_none());
}
#[test]
fn decode_token() {
let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUiLCJleHAiOjI1MzI1MjQ4OTF9.9r56oF7ZliOBlOAyiOFperTGxBtPykRQiWNFxhDCW98";
let claims = decode::<Claims>(token, Key::Hmac(b"secret"), &Validation::default());
println!("{:?}", claims);
claims.unwrap();
}
#[test]
#[should_panic(expected = "InvalidToken")]
fn decode_token_missing_parts() {
let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9";
let claims = decode::<Claims>(token, Key::Hmac(b"secret"), &Validation::default());
claims.unwrap();
}
#[test]
#[should_panic(expected = "InvalidSignature")]
fn decode_token_invalid_signature() {
let token =
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUifQ.wrong";
let claims = decode::<Claims>(token, Key::Hmac(b"secret"), &Validation::default());
claims.unwrap();
}
#[test]
#[should_panic(expected = "InvalidAlgorithm")]
fn decode_token_wrong_algorithm() {
let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUifQ.I1BvFoHe94AFf09O6tDbcSB8-jp8w6xZqmyHIwPeSdY";
let claims = decode::<Claims>(token, Key::Hmac(b"secret"), &Validation::new(Algorithm::RS512));
claims.unwrap();
}
#[test]
fn decode_token_with_bytes_secret() {
let token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUiLCJleHAiOjI1MzI1MjQ4OTF9.Hm0yvKH25TavFPz7J_coST9lZFYH1hQo0tvhvImmaks";
let claims = decode::<Claims>(token, Key::Hmac(b"\x01\x02\x03"), &Validation::default());
assert!(claims.is_ok());
}
#[test]
fn decode_header_only() {
let token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJjb21wYW55IjoiMTIzNDU2Nzg5MCIsInN1YiI6IkpvaG4gRG9lIn0.S";
let header = decode_header(token).unwrap();
assert_eq!(header.alg, Algorithm::HS256);
assert_eq!(header.typ, Some("JWT".to_string()));
}
#[test]
fn dangerous_unsafe_decode_token() {
let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUiLCJleHAiOjI1MzI1MjQ4OTF9.9r56oF7ZliOBlOAyiOFperTGxBtPykRQiWNFxhDCW98";
let claims = dangerous_unsafe_decode::<Claims>(token);
claims.unwrap();
}
#[test]
#[should_panic(expected = "InvalidToken")]
fn dangerous_unsafe_decode_token_missing_parts() {
let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9";
let claims = dangerous_unsafe_decode::<Claims>(token);
claims.unwrap();
}
#[test]
fn dangerous_unsafe_decode_token_invalid_signature() {
let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUiLCJleHAiOjI1MzI1MjQ4OTF9.wrong";
let claims = dangerous_unsafe_decode::<Claims>(token);
claims.unwrap();
}
#[test]
fn dangerous_unsafe_decode_token_wrong_algorithm() {
let token = "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUiLCJleHAiOjI1MzI1MjQ4OTF9.fLxey-hxAKX5rNHHIx1_Ch0KmrbiuoakDVbsJjLWrx8fbjKjrPuWMYEJzTU3SBnYgnZokC-wqSdqckXUOunC-g";
let claims = dangerous_unsafe_decode::<Claims>(token);
claims.unwrap();
}
// https://github.com/Keats/jsonwebtoken/issues/51
#[test]
fn does_validation_in_right_order() {
let my_claims = Claims {
sub: "b@b.com".to_string(),
company: "ACME".to_string(),
exp: Utc::now().timestamp() + 10000,
};
let token = encode(&Header::default(), &my_claims, Key::Hmac(b"secret")).unwrap();
let v = Validation {
leeway: 5,
validate_exp: true,
iss: Some("iss no check".to_string()),
sub: Some("sub no check".to_string()),
..Validation::default()
};
let res = decode::<Claims>(&token, Key::Hmac(b"secret"), &v);
assert!(res.is_err());
println!("{:?}", res);
//assert!(res.is_ok());
}
#[test]
fn generate_algorithm_enum_from_str() {
assert!(Algorithm::from_str("HS256").is_ok());
assert!(Algorithm::from_str("HS384").is_ok());
assert!(Algorithm::from_str("HS512").is_ok());
assert!(Algorithm::from_str("RS256").is_ok());
assert!(Algorithm::from_str("RS384").is_ok());
assert!(Algorithm::from_str("RS512").is_ok());
assert!(Algorithm::from_str("PS256").is_ok());
assert!(Algorithm::from_str("PS384").is_ok());
assert!(Algorithm::from_str("PS512").is_ok());
assert!(Algorithm::from_str("").is_err());
}
mod ec;
mod rsa;

View File

@ -1,10 +1,6 @@
extern crate jsonwebtoken;
#[macro_use]
extern crate serde_derive;
extern crate chrono;
use chrono::Utc;
use jsonwebtoken::{decode, decode_pem, encode, sign, verify, Algorithm, Header, Key, Validation};
use serde_derive::{Deserialize, Serialize};
const RSA_ALGORITHMS: &[Algorithm] = &[
Algorithm::RS256,
@ -126,3 +122,10 @@ fn rsa_modulus_exponent() {
.unwrap();
assert!(is_valid);
}
#[test]
#[should_panic(expected = "InvalidKeyFormat")]
fn fails_with_non_pkcs8_key_format() {
let privkey = include_bytes!("private_rsa_key.der");
let _encrypted = sign("hello world", Key::Der(&privkey[..]), Algorithm::ES256).unwrap();
}