1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
use core::str::FromStr;
use super::{Algorithm, Jwk, TokenType, Zip};
use crate::{b64, error::DecodeError};
use alloc::{string::String, vec::Vec};
use base64::engine::{general_purpose::URL_SAFE_NO_PAD, Engine};
use serde::{Deserialize, Serialize};
use url::Url;
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct Header {
/// Specifies the cryptographic algorithm used to secure the JWT.
#[serde(rename = "alg")]
pub algorithm: Algorithm,
/// The `"kid"` field is used to identify the key used to sign the JWT.
#[serde(rename = "kid", skip_serializing_if = "Option::is_none")]
pub key_id: Option<String>,
/// The `"cty"` field is used to indicate the MIME type of the token's payload.
/// This field is optional, but if present, its value should be a string that
/// identifies the type of data in the token's payload.
///
/// The value of the "cty" field can be any valid MIME media type. For example,
/// it could be set to "application/json" to indicate that the payload is a JSON
/// object, or "text/plain" to indicate that the payload is plain text.
#[serde(rename = "cty", skip_serializing_if = "Option::is_none")]
pub content_type: Option<String>,
/// The `"typ"` is used to indicate the type of the token.
///
/// The value of the "typ" field is typically set to "JWT" to indicate that
/// the token is a JSON Web Token.
#[serde(rename = "typ", skip_serializing_if = "Option::is_none")]
pub token_type: Option<TokenType>,
/// the `"jku"`field is used to specify the URL where the JWK set can be
/// found.
#[serde(rename = "jku", skip_serializing_if = "Option::is_none")]
pub jwks_url: Option<Url>,
/// The `"jwk"` field can be used to provide the JWK used to sign the JWT.
#[serde(skip_serializing_if = "Option::is_none")]
pub jwk: Option<Jwk>,
/// the `"x5u"` field is used to specify the URL where the X.509 certificate
/// chain can be found.
#[serde(rename = "x5u", skip_serializing_if = "Option::is_none")]
pub x509_url: Option<url::Url>,
/// the `"x5c"` field is used to provide the X.509 certificate chain.
#[serde(
rename = "x5c",
with = "b64::optional_seq_url_safe",
skip_serializing_if = "Option::is_none",
default
)]
pub x509_cert_chain: Option<Vec<Vec<u8>>>,
/// The value of the `"x5t"` field is a base64_url encoded string that represents
/// the SHA-1 thumbprint of the X.509 certificate. The SHA-1 thumbprint is
/// calculated by taking the SHA-1 hash of the DER-encoded X.509 certificate
/// and then base64-encoding the result.
#[serde(
rename = "x5t",
with = "b64::optional_url_safe",
skip_serializing_if = "Option::is_none",
default
)]
pub x509_cert_sha1_thumbprint: Option<Vec<u8>>,
/// The "x5t#S256" field in a JWT (JSON Web Token) header is used to include
/// the SHA-256 thumbprint of the X.509 certificate that was used to sign
/// the JWT.
///
/// The value of the "x5t#S256" field is a base64-encoded string that
/// represents the SHA-256 thumbprint of the X.509 certificate. The SHA-256
/// thumbprint is calculated by taking the SHA-256 hash of the DER-encoded
/// X.509 certificate and then base64-encoding the result.
#[serde(
rename = "x5t#S256",
with = "b64::optional_url_safe",
skip_serializing_if = "Option::is_none",
default
)]
pub x509_cert_sha256_thumbprint: Option<Vec<u8>>,
/// The `"crit"` field is used to indicate that extensions to this
/// specification and/or [JWS] are being used that MUST be understood and
/// processed. If the "crit" field is not understood, then the JWT must
/// be rejected.
#[serde(rename = "crit", skip_serializing_if = "Vec::is_empty", default)]
pub critical: Vec<String>,
#[serde(rename = "enc", skip_serializing_if = "Option::is_none")]
pub encryption: Option<String>, // TODO: the possible values need to be added to the Encryption enum
#[serde(rename = "zip", skip_serializing_if = "Option::is_none")]
pub zip: Option<Zip>,
#[serde(rename = "iv", skip_serializing_if = "Option::is_none")]
pub iv: Option<Vec<u8>>,
#[serde(flatten)]
pub additional_fields: serde_json::Map<String, serde_json::Value>,
}
impl TryFrom<&str> for Header {
type Error = DecodeError;
fn try_from(value: &str) -> Result<Self, Self::Error> {
Self::try_from(value.as_bytes())
}
}
impl FromStr for Header {
type Err = DecodeError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Self::try_from(s)
}
}
impl TryFrom<&[u8]> for Header {
type Error = DecodeError;
fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
let decoded = URL_SAFE_NO_PAD.decode(value)?;
Ok(serde_json::from_slice(&decoded)?)
}
}
impl TryFrom<String> for Header {
type Error = DecodeError;
fn try_from(value: String) -> Result<Self, Self::Error> {
Self::try_from(value.as_bytes())
}
}
impl TryFrom<&String> for Header {
type Error = DecodeError;
fn try_from(value: &String) -> Result<Self, Self::Error> {
Self::try_from(value.as_bytes())
}
}