/rust/registry/src/index.crates.io-1949cf8c6b5b557f/jsonwebtoken-10.3.0/src/header.rs
Line | Count | Source |
1 | | use std::collections::HashMap; |
2 | | use std::result; |
3 | | |
4 | | use base64::{Engine, engine::general_purpose::STANDARD}; |
5 | | use serde::{Deserialize, Deserializer, Serialize, Serializer}; |
6 | | |
7 | | use crate::algorithms::Algorithm; |
8 | | use crate::errors::Result; |
9 | | use crate::jwk::Jwk; |
10 | | use crate::serialization::b64_decode; |
11 | | |
12 | | const ZIP_SERIAL_DEFLATE: &str = "DEF"; |
13 | | const ENC_A128CBC_HS256: &str = "A128CBC-HS256"; |
14 | | const ENC_A192CBC_HS384: &str = "A192CBC-HS384"; |
15 | | const ENC_A256CBC_HS512: &str = "A256CBC-HS512"; |
16 | | const ENC_A128GCM: &str = "A128GCM"; |
17 | | const ENC_A192GCM: &str = "A192GCM"; |
18 | | const 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)] |
27 | | pub enum Enc { |
28 | | A128CBC_HS256, |
29 | | A192CBC_HS384, |
30 | | A256CBC_HS512, |
31 | | A128GCM, |
32 | | A192GCM, |
33 | | A256GCM, |
34 | | Other(String), |
35 | | } |
36 | | |
37 | | impl Serialize for Enc { |
38 | 0 | fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error> |
39 | 0 | where |
40 | 0 | S: Serializer, |
41 | | { |
42 | 0 | match self { |
43 | 0 | Enc::A128CBC_HS256 => ENC_A128CBC_HS256, |
44 | 0 | Enc::A192CBC_HS384 => ENC_A192CBC_HS384, |
45 | 0 | Enc::A256CBC_HS512 => ENC_A256CBC_HS512, |
46 | 0 | Enc::A128GCM => ENC_A128GCM, |
47 | 0 | Enc::A192GCM => ENC_A192GCM, |
48 | 0 | Enc::A256GCM => ENC_A256GCM, |
49 | 0 | Enc::Other(v) => v, |
50 | | } |
51 | 0 | .serialize(serializer) |
52 | 0 | } Unexecuted instantiation: <jsonwebtoken::header::Enc as serde_core::ser::Serialize>::serialize::<&mut serde_json::ser::Serializer<&mut alloc::vec::Vec<u8>>> Unexecuted instantiation: <jsonwebtoken::header::Enc as serde_core::ser::Serialize>::serialize::<_> |
53 | | } |
54 | | |
55 | | impl<'de> Deserialize<'de> for Enc { |
56 | 0 | fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error> |
57 | 0 | where |
58 | 0 | D: Deserializer<'de>, |
59 | | { |
60 | 0 | let s = String::deserialize(deserializer)?; |
61 | 0 | match s.as_str() { |
62 | 0 | ENC_A128CBC_HS256 => return Ok(Enc::A128CBC_HS256), |
63 | 0 | ENC_A192CBC_HS384 => return Ok(Enc::A192CBC_HS384), |
64 | 0 | ENC_A256CBC_HS512 => return Ok(Enc::A256CBC_HS512), |
65 | 0 | ENC_A128GCM => return Ok(Enc::A128GCM), |
66 | 0 | ENC_A192GCM => return Ok(Enc::A192GCM), |
67 | 0 | ENC_A256GCM => return Ok(Enc::A256GCM), |
68 | 0 | _ => (), |
69 | | } |
70 | 0 | Ok(Enc::Other(s)) |
71 | 0 | } |
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)] |
78 | | pub enum Zip { |
79 | | Deflate, |
80 | | Other(String), |
81 | | } |
82 | | |
83 | | impl Serialize for Zip { |
84 | 0 | fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error> |
85 | 0 | where |
86 | 0 | S: Serializer, |
87 | | { |
88 | 0 | match self { |
89 | 0 | Zip::Deflate => ZIP_SERIAL_DEFLATE, |
90 | 0 | Zip::Other(v) => v, |
91 | | } |
92 | 0 | .serialize(serializer) |
93 | 0 | } Unexecuted instantiation: <jsonwebtoken::header::Zip as serde_core::ser::Serialize>::serialize::<&mut serde_json::ser::Serializer<&mut alloc::vec::Vec<u8>>> Unexecuted instantiation: <jsonwebtoken::header::Zip as serde_core::ser::Serialize>::serialize::<_> |
94 | | } |
95 | | |
96 | | impl<'de> Deserialize<'de> for Zip { |
97 | 0 | fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error> |
98 | 0 | where |
99 | 0 | D: Deserializer<'de>, |
100 | | { |
101 | 0 | let s = String::deserialize(deserializer)?; |
102 | 0 | match s.as_str() { |
103 | 0 | ZIP_SERIAL_DEFLATE => Ok(Zip::Deflate), |
104 | 0 | _ => Ok(Zip::Other(s)), |
105 | | } |
106 | 0 | } |
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)] |
112 | | pub 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 | | |
193 | | impl Header { |
194 | | /// Returns a JWT header with the algorithm given |
195 | 0 | pub fn new(algorithm: Algorithm) -> Self { |
196 | 0 | Header { |
197 | 0 | typ: Some("JWT".to_string()), |
198 | 0 | alg: algorithm, |
199 | 0 | cty: None, |
200 | 0 | jku: None, |
201 | 0 | jwk: None, |
202 | 0 | kid: None, |
203 | 0 | x5u: None, |
204 | 0 | x5c: None, |
205 | 0 | x5t: None, |
206 | 0 | x5t_s256: None, |
207 | 0 | crit: None, |
208 | 0 | enc: None, |
209 | 0 | zip: None, |
210 | 0 | url: None, |
211 | 0 | nonce: None, |
212 | 0 | extras: Default::default(), |
213 | 0 | } |
214 | 0 | } |
215 | | |
216 | | /// Converts an encoded part into the Header struct if possible |
217 | 0 | pub(crate) fn from_encoded<T: AsRef<[u8]>>(encoded_part: T) -> Result<Self> { |
218 | 0 | let decoded = b64_decode(encoded_part)?; |
219 | 0 | Ok(serde_json::from_slice(&decoded)?) |
220 | 0 | } |
221 | | |
222 | | /// Decodes the X.509 certificate chain into ASN.1 DER format. |
223 | 0 | pub fn x5c_der(&self) -> Result<Option<Vec<Vec<u8>>>> { |
224 | 0 | Ok(self |
225 | 0 | .x5c |
226 | 0 | .as_ref() |
227 | 0 | .map(|b64_certs| { |
228 | 0 | b64_certs.iter().map(|x| STANDARD.decode(x)).collect::<result::Result<_, _>>() |
229 | 0 | }) |
230 | 0 | .transpose()?) |
231 | 0 | } |
232 | | } |
233 | | |
234 | | impl Default for Header { |
235 | | /// Returns a JWT header using the default Algorithm, HS256 |
236 | 0 | fn default() -> Self { |
237 | 0 | Header::new(Algorithm::default()) |
238 | 0 | } |
239 | | } |