From d30a7599a8df887754f8fa8b469e13068ab7e7ed Mon Sep 17 00:00:00 2001 From: Mike Engel Date: Sat, 3 Mar 2018 10:50:03 -0700 Subject: [PATCH] Add a method to decode a token without signature validation - Solves #48 - `dangerous_unsafe_decode` - No docs (aside from cargo) since people probably shouldn't use it --- src/lib.rs | 29 +++++++++++++++++++++++++++++ tests/lib.rs | 31 ++++++++++++++++++++++++++++++- 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 2f1f4ab..c34e3a4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -122,6 +122,35 @@ pub fn decode(token: &str, key: &[u8], validation: &Validat Ok(TokenData { header: header, claims: decoded_claims }) } +/// Decode a token without any signature validation into a struct containing 2 fields: `claims` and `header`. +/// +/// NOTE: Do not use this unless you know what you are doing! If the token's signature is invalid, it will *not* return an error. +/// +/// ```rust,ignore +/// #[macro_use] +/// extern crate serde_derive; +/// use jsonwebtoken::{dangerous_unsafe_decode, Validation, Algorithm}; +/// +/// #[derive(Debug, Serialize, Deserialize)] +/// struct Claims { +/// sub: String, +/// company: String +/// } +/// +/// let token = "a.jwt.token".to_string(); +/// // Claims is a struct that implements Deserialize +/// let token_data = dangerous_unsafe_decode::(&token, &Validation::new(Algorithm::HS256)); +/// ``` +pub fn dangerous_unsafe_decode(token: &str) -> Result> { + let (_, signing_input) = expect_two!(token.rsplitn(2, '.')); + let (claims, header) = expect_two!(signing_input.rsplitn(2, '.')); + let header: Header = from_jwt_part(header)?; + + let (decoded_claims, _): (T, _) = from_jwt_part_claims(claims)?; + + Ok(TokenData { header: header, claims: decoded_claims }) +} + /// Decode a token and return the Header. This is not doing any kind of validation: it is meant to be /// used when you don't know which `alg` the token is using and want to find out. /// diff --git a/tests/lib.rs b/tests/lib.rs index 9e6217f..d1eb579 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -2,7 +2,7 @@ extern crate jsonwebtoken; #[macro_use] extern crate serde_derive; -use jsonwebtoken::{encode, decode, decode_header, Algorithm, Header, sign, verify, Validation}; +use jsonwebtoken::{encode, decode, decode_header, dangerous_unsafe_decode, Algorithm, Header, sign, verify, Validation}; #[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] @@ -103,3 +103,32 @@ fn decode_header_only() { assert_eq!(header.alg, Algorithm::HS256); assert_eq!(header.typ, Some("JWT".to_string())); } + +#[test] +fn dangerous_unsafe_decode_token() { + let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUifQ.I1BvFoHe94AFf09O6tDbcSB8-jp8w6xZqmyHIwPeSdY"; + let claims = dangerous_unsafe_decode::(token); + claims.unwrap(); +} + +#[test] +#[should_panic(expected = "InvalidToken")] +fn dangerous_unsafe_decode_token_missing_parts() { + let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9"; + let claims = dangerous_unsafe_decode::(token); + claims.unwrap(); +} + +#[test] +fn dangerous_unsafe_decode_token_invalid_signature() { + let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUifQ.wrong"; + let claims = dangerous_unsafe_decode::(token); + claims.unwrap(); +} + +#[test] +fn dangerous_unsafe_decode_token_wrong_algorithm() { + let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUifQ.I1BvFoHe94AFf09O6tDbcSB8-jp8w6xZqmyHIwPeSdY"; + let claims = dangerous_unsafe_decode::(token); + claims.unwrap(); +}