truelayer_signing/
jws.rs

1use std::borrow::Cow;
2
3use indexmap::IndexMap;
4
5use crate::http::HeaderName;
6
7/// `Tl-Signature` header.
8#[derive(Debug, serde::Serialize, serde::Deserialize)]
9pub struct JwsHeader<'a> {
10    /// Algorithm, should be `ES512`.
11    pub alg: JwsAlgorithm,
12    /// Signing key id.
13    pub kid: Cow<'a, str>,
14    /// Signing scheme version, e.g. `"2"`.
15    ///
16    /// Empty implies v1, aka body-only signing.
17    #[serde(default)]
18    pub tl_version: Option<TlVersion>,
19    /// Comma separated ordered headers used in the signature.
20    #[serde(default)]
21    pub tl_headers: Option<String>,
22    /// JSON Web Key URL. Used in webhook signatures providing the public key jwk url.
23    #[serde(default, skip_serializing_if = "Option::is_none")]
24    pub jku: Option<Cow<'a, str>>,
25}
26
27impl<'a> JwsHeader<'a> {
28    pub(crate) fn new_v2(
29        kid: &'a str,
30        headers: &IndexMap<HeaderName<'_>, &[u8]>,
31        jku: Option<&'a str>,
32    ) -> Self {
33        let header_keys = headers.keys().fold(String::new(), |mut all, next| {
34            if !all.is_empty() {
35                all.push(',');
36            }
37            all.push_str(next.0);
38            all
39        });
40        Self {
41            alg: JwsAlgorithm::ES512,
42            kid: Cow::Borrowed(kid),
43            tl_version: Some(TlVersion::V2),
44            tl_headers: Some(header_keys),
45            jku: jku.map(Cow::Borrowed),
46        }
47    }
48}
49
50#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
51pub enum TlVersion {
52    #[serde(rename = "1")]
53    V1,
54    #[serde(rename = "2")]
55    V2,
56}
57
58#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
59pub enum JwsAlgorithm {
60    #[serde(rename = "ES512")]
61    ES512,
62}