Skip to content

Commit

Permalink
Add a method to decode a token without signature validation
Browse files Browse the repository at this point in the history
- Solves Keats#48
- `dangerous_unsafe_decode`
- No docs (aside from cargo) since people probably shouldn't use it
  • Loading branch information
Mike Engel committed Mar 3, 2018
1 parent 96efaba commit fa84c2c
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 1 deletion.
33 changes: 33 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,39 @@ pub fn decode<T: DeserializeOwned>(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_unsave_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::<Claims>(&token, &Validation::new(Algorithm::HS256));
/// ```
pub fn dangerous_unsafe_decode<T: DeserializeOwned>(token: &str, validation: &Validation) -> Result<TokenData<T>> {
let (_, signing_input) = expect_two!(token.rsplitn(2, '.'));
let (claims, header) = expect_two!(signing_input.rsplitn(2, '.'));
let header: Header = from_jwt_part(header)?;

if !validation.algorithms.contains(&header.alg) {
return Err(ErrorKind::InvalidAlgorithm.into());
}

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.
///
Expand Down
32 changes: 31 additions & 1 deletion tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -103,3 +103,33 @@ 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::<Claims>(token, &Validation::default());
claims.unwrap();
}

#[test]
#[should_panic(expected = "InvalidToken")]
fn dangerous_unsafe_decode_token_missing_parts() {
let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9";
let claims = dangerous_unsafe_decode::<Claims>(token, &Validation::default());
claims.unwrap();
}

#[test]
fn dangerous_unsafe_decode_token_invalid_signature() {
let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUifQ.wrong";
let claims = dangerous_unsafe_decode::<Claims>(token, &Validation::default());
claims.unwrap();
}

#[test]
#[should_panic(expected = "InvalidAlgorithm")]
fn dangerous_unsafe_decode_token_wrong_algorithm() {
let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUifQ.I1BvFoHe94AFf09O6tDbcSB8-jp8w6xZqmyHIwPeSdY";
let claims = dangerous_unsafe_decode::<Claims>(token, &Validation::new(Algorithm::RS512));
claims.unwrap();
}

0 comments on commit fa84c2c

Please sign in to comment.