Skip to content

Commit

Permalink
Add APIs to jws::Compact for retrieval of parts without signature v…
Browse files Browse the repository at this point in the history
…erification (#88)

* Add APIs to `jws::Compact` for retrieval of parts without signature verification

Fixes #75

* Minor cleanups

* Fix formatting
  • Loading branch information
lawliet89 authored Aug 17, 2017
1 parent e578b40 commit 5492bc8
Showing 1 changed file with 97 additions and 6 deletions.
103 changes: 97 additions & 6 deletions src/jws.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,36 @@ where
Compact::Encoded(encoded) => encoded,
}
}

/// Without decoding and verifying the JWS, retrieve a copy of the header.
///
/// ## Warning
/// Use this at your own risk. It is not advisable to trust unverified content.
pub fn unverified_header(&self) -> Result<Header<H>, Error> {
match *self {
Compact::Decoded { .. } => Err(Error::UnsupportedOperation),
Compact::Encoded(ref compact) => compact.part(0),
}
}

/// Without decoding and verifying the JWS, retrieve a copy of the payload.
///
/// ## Warning
/// Use this at your own risk. It is not advisable to trust unverified content.
pub fn unverified_payload(&self) -> Result<T, Error> {
match *self {
Compact::Decoded { .. } => Err(Error::UnsupportedOperation),
Compact::Encoded(ref compact) => compact.part(1),
}
}

/// Get a copy of the signature
pub fn signature(&self) -> Result<Vec<u8>, Error> {
match *self {
Compact::Decoded { .. } => Err(Error::UnsupportedOperation),
Compact::Encoded(ref compact) => compact.part(2),
}
}
}

/// Convenience implementation for a Compact that contains a `ClaimsSet`
Expand Down Expand Up @@ -715,8 +745,8 @@ mod tests {
fn compact_jws_decode_token_invalid_signature_hs256() {
let token = Compact::<PrivateClaims, Empty>::new_encoded(
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.\
eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUifQ.\
pKscJVk7-aHxfmQKlaZxh5uhuKhGMAa-1F5IX5mfUwI",
eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUifQ.\
pKscJVk7-aHxfmQKlaZxh5uhuKhGMAa-1F5IX5mfUwI",
);
let claims = token.decode(
&Secret::Bytes("secret".to_string().into_bytes()),
Expand All @@ -730,8 +760,8 @@ mod tests {
fn compact_jws_decode_token_invalid_signature_rs256() {
let token = Compact::<PrivateClaims, Empty>::new_encoded(
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.\
eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUifQ.\
pKscJVk7-aHxfmQKlaZxh5uhuKhGMAa-1F5IX5mfUwI",
eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUifQ.\
pKscJVk7-aHxfmQKlaZxh5uhuKhGMAa-1F5IX5mfUwI",
);
let public_key = Secret::public_key_from_file("test/fixtures/rsa_public_key.der").unwrap();
let claims = token.decode(&public_key, SignatureAlgorithm::RS256);
Expand All @@ -743,8 +773,8 @@ mod tests {
fn compact_jws_decode_token_wrong_algorithm() {
let token = Compact::<PrivateClaims, Empty>::new_encoded(
"eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.\
eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUifQ.\
pKscJVk7-aHxfmQKlaZxh5uhuKhGMAa-1F5IX5mfUwI",
eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUifQ.\
pKscJVk7-aHxfmQKlaZxh5uhuKhGMAa-1F5IX5mfUwI",
);
let claims = token.decode(
&Secret::Bytes("secret".to_string().into_bytes()),
Expand Down Expand Up @@ -804,4 +834,65 @@ mod tests {
let decoded: RegisteredHeader = not_err!(serde_json::from_str(&encoded));
assert_eq!(decoded, expected);
}

#[test]
fn unverified_header_is_returned_correctly() {
let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.\
eyJpc3MiOiJodHRwczovL3d3dy5hY21lLmNvbS8iLCJzdWIiOiJKb2huIERvZSIsImF1ZCI6Imh0dHM6Ly9hY21lL\
WN1c3RvbWVyLmNvbS8iLCJuYmYiOjEyMzQsImNvbXBhbnkiOiJBQ01FIiwiZGVwYXJ0bWVudCI6IlRvaWxldCBDbG\
VhbmluZyJ9.dnx1OmRZSFxjCD1ivy4lveTT-sxay5Fq6vY6jnJvqeI";

let encoded_token: Compact<ClaimsSet<PrivateClaims>, Empty> = Compact::new_encoded(&token);
let expected_header = From::from(RegisteredHeader {
algorithm: SignatureAlgorithm::HS256,
..Default::default()
});

let unverified_header = not_err!(encoded_token.unverified_header());
assert_eq!(unverified_header, expected_header);
}

#[test]
fn unverified_payload_is_returned_correctly() {
let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.\
eyJpc3MiOiJodHRwczovL3d3dy5hY21lLmNvbS8iLCJzdWIiOiJKb2huIERvZSIsImF1ZCI6Imh0dHM6Ly9hY21lL\
WN1c3RvbWVyLmNvbS8iLCJuYmYiOjEyMzQsImNvbXBhbnkiOiJBQ01FIiwiZGVwYXJ0bWVudCI6IlRvaWxldCBDbG\
VhbmluZyJ9.dnx1OmRZSFxjCD1ivy4lveTT-sxay5Fq6vY6jnJvqeI";

let encoded_token: Compact<ClaimsSet<PrivateClaims>, Empty> = Compact::new_encoded(&token);
let expected_payload = ClaimsSet::<PrivateClaims> {
registered: RegisteredClaims {
issuer: Some(not_err!(FromStr::from_str("https://www.acme.com"))),
subject: Some(not_err!(FromStr::from_str("John Doe"))),
audience: Some(SingleOrMultiple::Single(
not_err!(FromStr::from_str("htts://acme-customer.com")),
)),
not_before: Some(1234.into()),
..Default::default()
},
private: PrivateClaims {
department: "Toilet Cleaning".to_string(),
company: "ACME".to_string(),
},
};

let unverified_payload = not_err!(encoded_token.unverified_payload());
assert_eq!(unverified_payload, expected_payload);
}

#[test]
fn signature_is_returned_correctly() {
let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.\
eyJpc3MiOiJodHRwczovL3d3dy5hY21lLmNvbS8iLCJzdWIiOiJKb2huIERvZSIsImF1ZCI6Imh0dHM6Ly9hY21lL\
WN1c3RvbWVyLmNvbS8iLCJuYmYiOjEyMzQsImNvbXBhbnkiOiJBQ01FIiwiZGVwYXJ0bWVudCI6IlRvaWxldCBDbG\
VhbmluZyJ9.dnx1OmRZSFxjCD1ivy4lveTT-sxay5Fq6vY6jnJvqeI";

let encoded_token: Compact<ClaimsSet<PrivateClaims>, Empty> = Compact::new_encoded(&token);
let expected_signature: Vec<u8> = vec![118, 124, 117, 58, 100, 89, 72, 92, 99, 8, 61, 98,
191, 46, 37, 189, 228, 211, 250, 204, 90, 203, 145,
106, 234, 246, 58, 142, 114, 111, 169, 226];

let signature = not_err!(encoded_token.signature());
assert_eq!(signature, expected_signature);
}
}

0 comments on commit 5492bc8

Please sign in to comment.