jsonwebtoken/
header.rs

1use std::collections::HashMap;
2use std::result;
3
4use base64::{Engine, engine::general_purpose::STANDARD};
5use serde::{Deserialize, Deserializer, Serialize, Serializer};
6
7use crate::algorithms::Algorithm;
8use crate::errors::Result;
9use crate::jwk::Jwk;
10use crate::serialization::b64_decode;
11
12const ZIP_SERIAL_DEFLATE: &str = "DEF";
13const ENC_A128CBC_HS256: &str = "A128CBC-HS256";
14const ENC_A192CBC_HS384: &str = "A192CBC-HS384";
15const ENC_A256CBC_HS512: &str = "A256CBC-HS512";
16const ENC_A128GCM: &str = "A128GCM";
17const ENC_A192GCM: &str = "A192GCM";
18const ENC_A256GCM: &str = "A256GCM";
19
20/// Encryption algorithm for encrypted payloads.
21///
22/// Defined in [RFC7516#4.1.2](https://datatracker.ietf.org/doc/html/rfc7516#section-4.1.2).
23///
24/// Values defined in [RFC7518#5.1](https://datatracker.ietf.org/doc/html/rfc7518#section-5.1).
25#[derive(Debug, Clone, PartialEq, Eq, Hash)]
26#[allow(clippy::upper_case_acronyms, non_camel_case_types)]
27pub enum Enc {
28    A128CBC_HS256,
29    A192CBC_HS384,
30    A256CBC_HS512,
31    A128GCM,
32    A192GCM,
33    A256GCM,
34    Other(String),
35}
36
37impl Serialize for Enc {
38    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
39    where
40        S: Serializer,
41    {
42        match self {
43            Enc::A128CBC_HS256 => ENC_A128CBC_HS256,
44            Enc::A192CBC_HS384 => ENC_A192CBC_HS384,
45            Enc::A256CBC_HS512 => ENC_A256CBC_HS512,
46            Enc::A128GCM => ENC_A128GCM,
47            Enc::A192GCM => ENC_A192GCM,
48            Enc::A256GCM => ENC_A256GCM,
49            Enc::Other(v) => v,
50        }
51        .serialize(serializer)
52    }
53}
54
55impl<'de> Deserialize<'de> for Enc {
56    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
57    where
58        D: Deserializer<'de>,
59    {
60        let s = String::deserialize(deserializer)?;
61        match s.as_str() {
62            ENC_A128CBC_HS256 => return Ok(Enc::A128CBC_HS256),
63            ENC_A192CBC_HS384 => return Ok(Enc::A192CBC_HS384),
64            ENC_A256CBC_HS512 => return Ok(Enc::A256CBC_HS512),
65            ENC_A128GCM => return Ok(Enc::A128GCM),
66            ENC_A192GCM => return Ok(Enc::A192GCM),
67            ENC_A256GCM => return Ok(Enc::A256GCM),
68            _ => (),
69        }
70        Ok(Enc::Other(s))
71    }
72}
73
74/// Compression applied to plaintext.
75///
76/// Defined in [RFC7516#4.1.3](https://datatracker.ietf.org/doc/html/rfc7516#section-4.1.3).
77#[derive(Debug, Clone, PartialEq, Eq, Hash)]
78pub enum Zip {
79    Deflate,
80    Other(String),
81}
82
83impl Serialize for Zip {
84    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
85    where
86        S: Serializer,
87    {
88        match self {
89            Zip::Deflate => ZIP_SERIAL_DEFLATE,
90            Zip::Other(v) => v,
91        }
92        .serialize(serializer)
93    }
94}
95
96impl<'de> Deserialize<'de> for Zip {
97    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
98    where
99        D: Deserializer<'de>,
100    {
101        let s = String::deserialize(deserializer)?;
102        match s.as_str() {
103            ZIP_SERIAL_DEFLATE => Ok(Zip::Deflate),
104            _ => Ok(Zip::Other(s)),
105        }
106    }
107}
108
109/// A basic JWT header, the alg defaults to HS256 and typ is automatically
110/// set to `JWT`. All the other fields are optional.
111#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
112pub struct Header {
113    /// The type of JWS: it can only be "JWT" here
114    ///
115    /// Defined in [RFC7515#4.1.9](https://tools.ietf.org/html/rfc7515#section-4.1.9).
116    #[serde(skip_serializing_if = "Option::is_none")]
117    pub typ: Option<String>,
118    /// The algorithm used
119    ///
120    /// Defined in [RFC7515#4.1.1](https://tools.ietf.org/html/rfc7515#section-4.1.1).
121    pub alg: Algorithm,
122    /// Content type
123    ///
124    /// Defined in [RFC7519#5.2](https://tools.ietf.org/html/rfc7519#section-5.2).
125    #[serde(skip_serializing_if = "Option::is_none")]
126    pub cty: Option<String>,
127    /// JSON Key URL
128    ///
129    /// Defined in [RFC7515#4.1.2](https://tools.ietf.org/html/rfc7515#section-4.1.2).
130    #[serde(skip_serializing_if = "Option::is_none")]
131    pub jku: Option<String>,
132    /// JSON Web Key
133    ///
134    /// Defined in [RFC7515#4.1.3](https://tools.ietf.org/html/rfc7515#section-4.1.3).
135    #[serde(skip_serializing_if = "Option::is_none")]
136    pub jwk: Option<Jwk>,
137    /// Key ID
138    ///
139    /// Defined in [RFC7515#4.1.4](https://tools.ietf.org/html/rfc7515#section-4.1.4).
140    #[serde(skip_serializing_if = "Option::is_none")]
141    pub kid: Option<String>,
142    /// X.509 URL
143    ///
144    /// Defined in [RFC7515#4.1.5](https://tools.ietf.org/html/rfc7515#section-4.1.5).
145    #[serde(skip_serializing_if = "Option::is_none")]
146    pub x5u: Option<String>,
147    /// X.509 certificate chain. A Vec of base64 encoded ASN.1 DER certificates.
148    ///
149    /// Defined in [RFC7515#4.1.6](https://tools.ietf.org/html/rfc7515#section-4.1.6).
150    #[serde(skip_serializing_if = "Option::is_none")]
151    pub x5c: Option<Vec<String>>,
152    /// X.509 SHA1 certificate thumbprint
153    ///
154    /// Defined in [RFC7515#4.1.7](https://tools.ietf.org/html/rfc7515#section-4.1.7).
155    #[serde(skip_serializing_if = "Option::is_none")]
156    pub x5t: Option<String>,
157    /// X.509 SHA256 certificate thumbprint
158    ///
159    /// Defined in [RFC7515#4.1.8](https://tools.ietf.org/html/rfc7515#section-4.1.8).
160    ///
161    /// This will be serialized/deserialized as "x5t#S256", as defined by the RFC.
162    #[serde(skip_serializing_if = "Option::is_none")]
163    #[serde(rename = "x5t#S256")]
164    pub x5t_s256: Option<String>,
165    /// Critical - indicates header fields that must be understood by the receiver.
166    ///
167    /// Defined in [RFC7515#4.1.6](https://tools.ietf.org/html/rfc7515#section-4.1.6).
168    #[serde(skip_serializing_if = "Option::is_none")]
169    pub crit: Option<Vec<String>>,
170    /// See `Enc` for description.
171    #[serde(skip_serializing_if = "Option::is_none")]
172    pub enc: Option<Enc>,
173    /// See `Zip` for description.
174    #[serde(skip_serializing_if = "Option::is_none")]
175    pub zip: Option<Zip>,
176    /// ACME: The URL to which this JWS object is directed
177    ///
178    /// Defined in [RFC8555#6.4](https://datatracker.ietf.org/doc/html/rfc8555#section-6.4).
179    #[serde(skip_serializing_if = "Option::is_none")]
180    pub url: Option<String>,
181    /// ACME: Random data for preventing replay attacks.
182    ///
183    /// Defined in [RFC8555#6.5.2](https://datatracker.ietf.org/doc/html/rfc8555#section-6.5.2).
184    #[serde(skip_serializing_if = "Option::is_none")]
185    pub nonce: Option<String>,
186    /// Any additional non-standard headers not defined in [RFC7515#4.1](https://datatracker.ietf.org/doc/html/rfc7515#section-4.1).
187    /// Once serialized, all keys will be converted to fields at the root level of the header payload
188    /// Ex: Dict("custom" -> "header") will be converted to "{"typ": "JWT", ..., "custom": "header"}"
189    #[serde(flatten)]
190    pub extras: HashMap<String, String>,
191}
192
193impl Header {
194    /// Returns a JWT header with the algorithm given
195    pub fn new(algorithm: Algorithm) -> Self {
196        Header {
197            typ: Some("JWT".to_string()),
198            alg: algorithm,
199            cty: None,
200            jku: None,
201            jwk: None,
202            kid: None,
203            x5u: None,
204            x5c: None,
205            x5t: None,
206            x5t_s256: None,
207            crit: None,
208            enc: None,
209            zip: None,
210            url: None,
211            nonce: None,
212            extras: Default::default(),
213        }
214    }
215
216    /// Converts an encoded part into the Header struct if possible
217    pub(crate) fn from_encoded<T: AsRef<[u8]>>(encoded_part: T) -> Result<Self> {
218        let decoded = b64_decode(encoded_part)?;
219        Ok(serde_json::from_slice(&decoded)?)
220    }
221
222    /// Decodes the X.509 certificate chain into ASN.1 DER format.
223    pub fn x5c_der(&self) -> Result<Option<Vec<Vec<u8>>>> {
224        Ok(self
225            .x5c
226            .as_ref()
227            .map(|b64_certs| {
228                b64_certs.iter().map(|x| STANDARD.decode(x)).collect::<result::Result<_, _>>()
229            })
230            .transpose()?)
231    }
232}
233
234impl Default for Header {
235    /// Returns a JWT header using the default Algorithm, HS256
236    fn default() -> Self {
237        Header::new(Algorithm::default())
238    }
239}