1use std::borrow::Cow;
4
5use serde::{Deserialize, Serialize};
6
7use crate::algorithm::AlgorithmType;
8use crate::error::Error;
9use crate::ToBase64;
10
11pub trait JoseHeader {
14 fn algorithm_type(&self) -> AlgorithmType;
15
16 fn key_id(&self) -> Option<&str> {
17 None
18 }
19
20 fn type_(&self) -> Option<HeaderType> {
21 None
22 }
23
24 fn content_type(&self) -> Option<HeaderContentType> {
25 None
26 }
27}
28
29#[derive(Default, Debug, PartialEq, Serialize, Deserialize)]
32pub struct Header {
33 #[serde(rename = "alg")]
34 pub algorithm: AlgorithmType,
35
36 #[serde(rename = "kid", skip_serializing_if = "Option::is_none")]
37 pub key_id: Option<String>,
38
39 #[serde(rename = "typ", skip_serializing_if = "Option::is_none")]
40 pub type_: Option<HeaderType>,
41
42 #[serde(rename = "cty", skip_serializing_if = "Option::is_none")]
43 pub content_type: Option<HeaderContentType>,
44}
45
46impl JoseHeader for Header {
47 fn algorithm_type(&self) -> AlgorithmType {
48 self.algorithm
49 }
50
51 fn key_id(&self) -> Option<&str> {
52 self.key_id.as_deref()
53 }
54
55 fn type_(&self) -> Option<HeaderType> {
56 self.type_
57 }
58
59 fn content_type(&self) -> Option<HeaderContentType> {
60 self.content_type
61 }
62}
63
64#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
65#[serde(rename_all = "UPPERCASE")]
66pub enum HeaderType {
67 #[serde(rename = "JWT")]
68 JsonWebToken,
69}
70
71#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
72pub enum HeaderContentType {
73 #[serde(rename = "JWT")]
74 JsonWebToken,
75}
76
77pub struct PrecomputedAlgorithmOnlyHeader(pub AlgorithmType);
80
81impl JoseHeader for PrecomputedAlgorithmOnlyHeader {
82 fn algorithm_type(&self) -> AlgorithmType {
83 let PrecomputedAlgorithmOnlyHeader(algorithm_type) = *self;
84 algorithm_type
85 }
86}
87
88impl ToBase64 for PrecomputedAlgorithmOnlyHeader {
89 fn to_base64(&self) -> Result<Cow<'static, str>, Error> {
90 let precomputed_str = match self.algorithm_type() {
91 AlgorithmType::Hs256 => "eyJhbGciOiAiSFMyNTYifQ",
92 AlgorithmType::Hs384 => "eyJhbGciOiAiSFMzODQifQ",
93 AlgorithmType::Hs512 => "eyJhbGciOiAiSFM1MTIifQ",
94 AlgorithmType::Rs256 => "eyJhbGciOiAiUlMyNTYifQ",
95 AlgorithmType::Rs384 => "eyJhbGciOiAiUlMzODQifQ",
96 AlgorithmType::Rs512 => "eyJhbGciOiAiUlM1MTIifQ",
97 AlgorithmType::Es256 => "eyJhbGciOiAiRVMyNTYifQ",
98 AlgorithmType::Es384 => "eyJhbGciOiAiRVMzODQifQ",
99 AlgorithmType::Es512 => "eyJhbGciOiAiRVM1MTIifQ",
100 AlgorithmType::Ps256 => "eyJhbGciOiAiUFMyNTYifQ",
101 AlgorithmType::Ps384 => "eyJhbGciOiAiUFMzODQifQ",
102 AlgorithmType::Ps512 => "eyJhbGciOiAiUFM1MTIifQ",
103 AlgorithmType::None => "eyJhbGciOiAibm9uZSJ9Cg",
104 };
105
106 Ok(Cow::Borrowed(precomputed_str))
107 }
108}
109
110#[derive(Serialize)]
113pub(crate) struct BorrowedKeyHeader<'a> {
114 #[serde(rename = "alg")]
115 pub algorithm: AlgorithmType,
116
117 #[serde(rename = "kid")]
118 pub key_id: &'a str,
119}
120
121impl<'a> JoseHeader for BorrowedKeyHeader<'a> {
122 fn algorithm_type(&self) -> AlgorithmType {
123 self.algorithm
124 }
125
126 fn key_id(&self) -> Option<&str> {
127 Some(self.key_id)
128 }
129}
130
131#[cfg(test)]
132mod tests {
133 use crate::algorithm::AlgorithmType;
134 use crate::error::Error;
135 use crate::header::{Header, HeaderType, PrecomputedAlgorithmOnlyHeader};
136 use crate::{FromBase64, ToBase64};
137
138 #[test]
139 fn from_base64() -> Result<(), Error> {
140 let enc = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9";
141 let header = Header::from_base64(enc)?;
142
143 assert_eq!(header.type_.unwrap(), HeaderType::JsonWebToken);
144 assert_eq!(header.algorithm, AlgorithmType::Hs256);
145
146 let enc = "eyJhbGciOiJSUzI1NiIsImtpZCI6IjFLU0YzZyJ9";
147 let header = Header::from_base64(enc)?;
148
149 assert_eq!(header.key_id.unwrap(), "1KSF3g".to_string());
150 assert_eq!(header.algorithm, AlgorithmType::Rs256);
151
152 Ok(())
153 }
154
155 #[test]
156 fn roundtrip() -> Result<(), Error> {
157 let header: Header = Default::default();
158 let enc = header.to_base64()?;
159 assert_eq!(header, Header::from_base64(&*enc)?);
160 Ok(())
161 }
162
163 #[test]
164 fn precomputed_headers() -> Result<(), Error> {
165 let algorithms = [
166 AlgorithmType::Hs256,
167 AlgorithmType::Hs384,
168 AlgorithmType::Hs512,
169 AlgorithmType::Rs256,
170 AlgorithmType::Rs384,
171 AlgorithmType::Rs512,
172 AlgorithmType::Es256,
173 AlgorithmType::Es384,
174 AlgorithmType::Es512,
175 AlgorithmType::Ps256,
176 AlgorithmType::Ps384,
177 AlgorithmType::Ps512,
178 AlgorithmType::None,
179 ];
180
181 for algorithm in algorithms.iter() {
182 let precomputed = PrecomputedAlgorithmOnlyHeader(*algorithm);
183 let precomputed_str = precomputed.to_base64()?;
184
185 let header = Header::from_base64(&*precomputed_str)?;
186 assert_eq!(*algorithm, header.algorithm);
187 }
188
189 Ok(())
190 }
191}