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#[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#[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#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
112pub struct Header {
113 #[serde(skip_serializing_if = "Option::is_none")]
117 pub typ: Option<String>,
118 pub alg: Algorithm,
122 #[serde(skip_serializing_if = "Option::is_none")]
126 pub cty: Option<String>,
127 #[serde(skip_serializing_if = "Option::is_none")]
131 pub jku: Option<String>,
132 #[serde(skip_serializing_if = "Option::is_none")]
136 pub jwk: Option<Jwk>,
137 #[serde(skip_serializing_if = "Option::is_none")]
141 pub kid: Option<String>,
142 #[serde(skip_serializing_if = "Option::is_none")]
146 pub x5u: Option<String>,
147 #[serde(skip_serializing_if = "Option::is_none")]
151 pub x5c: Option<Vec<String>>,
152 #[serde(skip_serializing_if = "Option::is_none")]
156 pub x5t: Option<String>,
157 #[serde(skip_serializing_if = "Option::is_none")]
163 #[serde(rename = "x5t#S256")]
164 pub x5t_s256: Option<String>,
165 #[serde(skip_serializing_if = "Option::is_none")]
169 pub crit: Option<Vec<String>>,
170 #[serde(skip_serializing_if = "Option::is_none")]
172 pub enc: Option<Enc>,
173 #[serde(skip_serializing_if = "Option::is_none")]
175 pub zip: Option<Zip>,
176 #[serde(skip_serializing_if = "Option::is_none")]
180 pub url: Option<String>,
181 #[serde(skip_serializing_if = "Option::is_none")]
185 pub nonce: Option<String>,
186 #[serde(flatten)]
190 pub extras: HashMap<String, String>,
191}
192
193impl Header {
194 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 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 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 fn default() -> Self {
237 Header::new(Algorithm::default())
238 }
239}