From 1d41b7650c29a49f063aefcae1c04d0bf0d2f8c3 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 9 Oct 2025 11:07:18 -0400 Subject: [PATCH] decoding: add `decode_header_as` function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Headers may contain custom fields. As an example, these fields may be used by implementations to choose the decoding key rather than disabling signature validation, parsing the payload, determining the key and *then* decoding securely. RFC 7519 ยง 5.3 explicitly calls out the ability to store `iss`, `sub`, and `aud` in the header. Using custom structures also allows users to avoid storing any unnecessary data when doing such pre-processing. See: https://datatracker.ietf.org/doc/html/rfc7519#section-5.3 Fixes: #435 --- src/decoding.rs | 27 +++++++++++++++++++++++++++ src/lib.rs | 2 +- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/decoding.rs b/src/decoding.rs index 6d1fc42f..b2028cad 100644 --- a/src/decoding.rs +++ b/src/decoding.rs @@ -357,6 +357,33 @@ pub fn decode_header(token: impl AsRef<[u8]>) -> Result
{ Header::from_encoded(header) } +/// Decode a JWT without any signature verification/validations and return its header as a custom type. +/// +/// If the token has an invalid format (ie 3 parts separated by a `.`), it will return an error. +/// +/// ```rust +/// use jsonwebtoken::decode_header_as; +/// use serde::Deserialize; +/// +/// #[derive(Deserialize)] +/// struct MyHeader { +/// iss: String, +/// } +/// +/// let token = "a.jwt.token".to_string(); +/// let header: Result = decode_header_as(&token); +/// ``` +pub fn decode_header_as(token: impl AsRef<[u8]>) -> Result +where + T: DeserializeOwned, +{ + let token = token.as_ref(); + let (_, message) = expect_two!(token.rsplitn(2, |b| *b == b'.')); + let (_, header) = expect_two!(message.rsplitn(2, |b| *b == b'.')); + let decoded = b64_decode(header)?; + Ok(serde_json::from_slice(&decoded)?) +} + pub(crate) fn verify_signature_body( message: &[u8], signature: &[u8], diff --git a/src/lib.rs b/src/lib.rs index 003bbdc1..4ce0ff7a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,7 +12,7 @@ compile_error!( compile_error!("at least one of the features \"rust_crypto\" or \"aws_lc_rs\" must be enabled"); pub use algorithms::Algorithm; -pub use decoding::{DecodingKey, TokenData, decode, decode_header}; +pub use decoding::{DecodingKey, TokenData, decode, decode_header, decode_header_as}; pub use encoding::{EncodingKey, encode}; pub use header::Header; pub use validation::{Validation, get_current_timestamp};