Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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()))?;
Expand Down
2 changes: 1 addition & 1 deletion benches/jwt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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| {
Expand Down
2 changes: 1 addition & 1 deletion examples/custom_header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()),
Expand Down
2 changes: 1 addition & 1 deletion src/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<String, String>,
pub extras: HashMap<String, serde_json::Value>,
}

impl Header {
Expand Down
33 changes: 25 additions & 8 deletions tests/hmac.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<Claims>(
Expand All @@ -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]
Expand All @@ -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::<Claims>(
Expand All @@ -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]
Expand Down Expand Up @@ -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<String, String>.
let token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsInVpZCI6MTgwNDQ0fQ.eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUiLCJleHAiOjI1MzI1MjQ4OTF9.orW-ZcVTziQ99c8lg5LcQk9YxITxS47pHWv-3nwcAhI";
let claims = decode::<Claims>(
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]
Expand Down