From 2aad217087cc677b1ff7d578f0afa33a734fede3 Mon Sep 17 00:00:00 2001 From: Adrian Black Date: Fri, 19 Feb 2021 12:17:59 -0800 Subject: [PATCH] add verify_sig fn (#161) * add verify_sig fn * fix missing comma * fmt whitespace changes --- src/decoding.rs | 64 +++++++++++++++++++++++++++++++++---------------- src/lib.rs | 2 +- 2 files changed, 45 insertions(+), 21 deletions(-) diff --git a/src/decoding.rs b/src/decoding.rs index a55bf6a..b393d7c 100644 --- a/src/decoding.rs +++ b/src/decoding.rs @@ -149,6 +149,43 @@ impl<'a> DecodingKey<'a> { } } +/// Verify signature of a JWT, and return header object and raw payload +/// +/// If the token or its signature is invalid, it will return an error. +/// +/// ```rust/// +/// use jsonwebtoken::{verify_sig, DecodingKey, Validation, Algorithm}; +/// +/// +/// let token = "a.jwt.token".to_string(); +/// let token_message = verify_sig(&token, &DecodingKey::from_secret("secret".as_ref()), &Validation::new(Algorithm::HS256)); +/// ``` +pub fn verify_sig( + token: &str, + key: &DecodingKey, + validation: &Validation, +) -> Result<(Header, String)> { + for alg in &validation.algorithms { + if key.family != alg.family() { + return Err(new_error(ErrorKind::InvalidAlgorithm)); + } + } + + let (signature, message) = expect_two!(token.rsplitn(2, '.')); + let (payload, header) = expect_two!(message.rsplitn(2, '.')); + let header = Header::from_encoded(header)?; + + if !validation.algorithms.contains(&header.alg) { + return Err(new_error(ErrorKind::InvalidAlgorithm)); + } + + if !verify(signature, message.as_bytes(), key, header.alg)? { + return Err(new_error(ErrorKind::InvalidSignature)); + } + + Ok((header, payload.to_string())) +} + /// Decode and validate a JWT /// /// If the token or its signature is invalid or the claims fail validation, it will return an error. @@ -172,28 +209,15 @@ pub fn decode( key: &DecodingKey, validation: &Validation, ) -> Result> { - for alg in &validation.algorithms { - if key.family != alg.family() { - return Err(new_error(ErrorKind::InvalidAlgorithm)); + match verify_sig(token, key, validation) { + Err(e) => Err(e), + Ok((header, claims)) => { + let (decoded_claims, claims_map): (T, _) = from_jwt_part_claims(claims)?; + validate(&claims_map, validation)?; + + Ok(TokenData { header, claims: decoded_claims }) } } - - let (signature, message) = expect_two!(token.rsplitn(2, '.')); - let (claims, header) = expect_two!(message.rsplitn(2, '.')); - let header = Header::from_encoded(header)?; - - if !validation.algorithms.contains(&header.alg) { - return Err(new_error(ErrorKind::InvalidAlgorithm)); - } - - if !verify(signature, message.as_bytes(), key, header.alg)? { - return Err(new_error(ErrorKind::InvalidSignature)); - } - - let (decoded_claims, claims_map): (T, _) = from_jwt_part_claims(claims)?; - validate(&claims_map, validation)?; - - Ok(TokenData { header, claims: decoded_claims }) } /// Decode a JWT without any signature verification/validations. diff --git a/src/lib.rs b/src/lib.rs index 9108341..3881160 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,7 +18,7 @@ mod validation; pub use algorithms::Algorithm; pub use decoding::{ dangerous_insecure_decode, dangerous_insecure_decode_with_validation, decode, decode_header, - DecodingKey, TokenData, + verify_sig, DecodingKey, TokenData, }; pub use encoding::{encode, EncodingKey}; pub use header::Header;