diff --git a/README.md b/README.md index 363387fe..aeaeda74 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,7 @@ let mut header = Header::new(Algorithm::HS512); header.kid = Some("blabla".to_owned()); let mut extras = HashMap::with_capacity(1); -extras.insert("custom".to_string(), "header".to_string()); +extras.insert("custom".to_string(), serde_json::Value::String("header".to_string())); header.extras = Some(extras); let token = encode(&header, &my_claims, &EncodingKey::from_secret("secret".as_ref()))?; diff --git a/benches/jwt.rs b/benches/jwt.rs index 6397d249..2fa78317 100644 --- a/benches/jwt.rs +++ b/benches/jwt.rs @@ -22,7 +22,7 @@ fn bench_encode_custom_extra_headers(c: &mut Criterion) { let claim = Claims { sub: "b@b.com".to_owned(), company: "ACME".to_owned() }; let key = EncodingKey::from_secret("secret".as_ref()); let mut extras = HashMap::with_capacity(1); - extras.insert("custom".to_string(), "header".to_string()); + extras.insert("custom".to_string(), serde_json::Value::String("header".to_string())); let header = &Header { extras, ..Default::default() }; c.bench_function("bench_encode", |b| { diff --git a/examples/custom_header.rs b/examples/custom_header.rs index 7c343d8f..ff27a305 100644 --- a/examples/custom_header.rs +++ b/examples/custom_header.rs @@ -17,7 +17,7 @@ fn main() { let key = b"secret"; let mut extras = HashMap::with_capacity(1); - extras.insert("custom".to_string(), "header".to_string()); + extras.insert("custom".to_string(), serde_json::Value::String("header".to_string())); let header = Header { kid: Some("signing_key".to_owned()), diff --git a/src/header.rs b/src/header.rs index 76b744a2..1fadc465 100644 --- a/src/header.rs +++ b/src/header.rs @@ -187,7 +187,7 @@ pub struct Header { /// Once serialized, all keys will be converted to fields at the root level of the header payload /// Ex: Dict("custom" -> "header") will be converted to "{"typ": "JWT", ..., "custom": "header"}" #[serde(flatten)] - pub extras: HashMap, + pub extras: HashMap, } impl Header { diff --git a/tests/hmac.rs b/tests/hmac.rs index f4f5968d..ff372930 100644 --- a/tests/hmac.rs +++ b/tests/hmac.rs @@ -68,7 +68,7 @@ fn encode_with_extra_custom_header() { exp: OffsetDateTime::now_utc().unix_timestamp() + 10000, }; let mut extras = HashMap::with_capacity(1); - extras.insert("custom".to_string(), "header".to_string()); + extras.insert("custom".to_string(), serde_json::Value::String("header".to_string())); let header = Header { kid: Some("kid".to_string()), extras, ..Default::default() }; let token = encode(&header, &my_claims, &EncodingKey::from_secret(b"secret")).unwrap(); let token_data = decode::( @@ -79,7 +79,7 @@ fn encode_with_extra_custom_header() { .unwrap(); assert_eq!(my_claims, token_data.claims); assert_eq!("kid", token_data.header.kid.unwrap()); - assert_eq!("header", token_data.header.extras.get("custom").unwrap().as_str()); + assert_eq!("header", token_data.header.extras.get("custom").unwrap().as_str().unwrap()); } #[test] @@ -91,8 +91,8 @@ fn encode_with_multiple_extra_custom_headers() { exp: OffsetDateTime::now_utc().unix_timestamp() + 10000, }; let mut extras = HashMap::with_capacity(2); - extras.insert("custom1".to_string(), "header1".to_string()); - extras.insert("custom2".to_string(), "header2".to_string()); + extras.insert("custom1".to_string(), serde_json::Value::String("header1".to_string())); + extras.insert("custom2".to_string(), serde_json::Value::String("header2".to_string())); let header = Header { kid: Some("kid".to_string()), extras, ..Default::default() }; let token = encode(&header, &my_claims, &EncodingKey::from_secret(b"secret")).unwrap(); let token_data = decode::( @@ -104,8 +104,8 @@ fn encode_with_multiple_extra_custom_headers() { assert_eq!(my_claims, token_data.claims); assert_eq!("kid", token_data.header.kid.unwrap()); let extras = token_data.header.extras; - assert_eq!("header1", extras.get("custom1").unwrap().as_str()); - assert_eq!("header2", extras.get("custom2").unwrap().as_str()); + assert_eq!("header1", extras.get("custom1").unwrap().as_str().unwrap()); + assert_eq!("header2", extras.get("custom2").unwrap().as_str().unwrap()); } #[test] @@ -156,8 +156,25 @@ fn decode_token_custom_headers() { assert_eq!(my_claims, claims.claims); assert_eq!("kid", claims.header.kid.unwrap()); let extras = claims.header.extras; - assert_eq!("header1", extras.get("custom1").unwrap().as_str()); - assert_eq!("header2", extras.get("custom2").unwrap().as_str()); + assert_eq!("header1", extras.get("custom1").unwrap().as_str().unwrap()); + assert_eq!("header2", extras.get("custom2").unwrap().as_str().unwrap()); +} + +#[test] +#[wasm_bindgen_test] +fn decode_token_with_non_string_extra_header() { + // Header: {"typ":"JWT","alg":"HS256","uid":180444} + // This token has an integer value in the header extras which previously + // caused deserialization to fail when extras was HashMap. + let token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsInVpZCI6MTgwNDQ0fQ.eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUiLCJleHAiOjI1MzI1MjQ4OTF9.orW-ZcVTziQ99c8lg5LcQk9YxITxS47pHWv-3nwcAhI"; + let claims = decode::( + token, + &DecodingKey::from_secret(b"secret"), + &Validation::new(Algorithm::HS256), + ); + assert!(claims.is_ok()); + let token_data = claims.unwrap(); + assert_eq!(180444, token_data.header.extras.get("uid").unwrap().as_u64().unwrap()); } #[test]