diff --git a/benches/jwt.rs b/benches/jwt.rs index 26f1f97..d45d193 100644 --- a/benches/jwt.rs +++ b/benches/jwt.rs @@ -23,10 +23,6 @@ fn bench_encode(b: &mut test::Bencher) { #[bench] fn bench_decode(b: &mut test::Bencher) { - let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ".to_owned(); - b.iter(|| decode::( - token.clone(), - "secret".to_owned(), - Algorithm::HS256 - )); + let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ"; + b.iter(|| decode::(token, "secret", Algorithm::HS256)); } diff --git a/examples/claims.rs b/examples/claims.rs index 006372d..4deb81b 100644 --- a/examples/claims.rs +++ b/examples/claims.rs @@ -21,7 +21,7 @@ fn main() { Err(_) => panic!() // in practice you would return the error }; - let claims = match decode::(token.to_owned(), key.to_owned(), Algorithm::HS256) { + let claims = match decode::(&token, key, Algorithm::HS256) { Ok(c) => c, Err(err) => match err { Error::InvalidToken => panic!(), // Example on how to handle a specific error diff --git a/src/lib.rs b/src/lib.rs index c0b221d..d25eee9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -98,15 +98,22 @@ pub fn encode>(claims: &T, secret: B, algorithm: Algorit /// Decode a token into a Claims struct /// If the token or its signature is invalid, it will return an error -pub fn decode(token: String, secret: String, algorithm: Algorithm) -> Result { - let parts: Vec<&str> = token.split(".").collect(); - if parts.len() != 3 { - return Err(Error::InvalidToken); +pub fn decode(token: &str, secret: &str, algorithm: Algorithm) -> Result { + macro_rules! expect_two { + ($iter:expr) => {{ + let mut i = $iter; // evaluate the expr + match (i.next(), i.next(), i.next()) { + (Some(first), Some(second), None) => (first, second), + _ => return Err(Error::InvalidToken) + } + }} } + let (signature, payload) = expect_two!(token.rsplitn(2, '.')); + let is_valid = verify( - parts[2], - &[parts[0], parts[1]].join("."), + signature, + payload, secret.as_bytes(), algorithm ); @@ -115,14 +122,14 @@ pub fn decode(token: String, secret: String, algorithm: Algorithm) -> R return Err(Error::InvalidSignature); } - // not reachable right now - let header = try!(Header::from_base64(parts[0])); + let (claims, header) = expect_two!(payload.rsplitn(2, '.')); + + let header = try!(Header::from_base64(header)); if header.alg != algorithm { return Err(Error::WrongAlgorithmHeader); } - let claims: T = try!(T::from_base64(parts[1])); - Ok(claims) + T::from_base64(claims) } #[cfg(test)] @@ -179,7 +186,7 @@ mod tests { company: "ACME".to_owned() }; let token = encode(&my_claims, "secret", Algorithm::HS256).unwrap(); - let claims = decode::(token.to_owned(), "secret".to_owned(), Algorithm::HS256).unwrap(); + let claims = decode::(&token, "secret", Algorithm::HS256).unwrap(); assert_eq!(my_claims, claims); } @@ -187,7 +194,7 @@ mod tests { #[should_panic(expected = "InvalidToken")] fn decode_token_missing_parts() { let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9"; - let claims = decode::(token.to_owned(), "secret".to_owned(), Algorithm::HS256); + let claims = decode::(token, "secret", Algorithm::HS256); claims.unwrap(); } @@ -195,7 +202,7 @@ mod tests { #[should_panic(expected = "InvalidSignature")] fn decode_token_invalid_signature() { let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUifQ.wrong"; - let claims = decode::(token.to_owned(), "secret".to_owned(), Algorithm::HS256); + let claims = decode::(token, "secret", Algorithm::HS256); claims.unwrap(); } }