1use crate::Error;
3use crate::codecs::CodecService;
4use crate::jsonwebtoken::{DecodingKey, EncodingKey, Header, Validation};
5use chrono::{TimeDelta, Utc};
6use serde::{Deserialize, Serialize, de::DeserializeOwned};
7use serde_with::skip_serializing_none;
8use std::collections::HashSet;
9use std::marker::PhantomData;
10
11#[derive(Serialize, Deserialize, Clone, Debug)]
15#[skip_serializing_none]
16pub struct RegisteredClaims {
17 #[serde(rename = "iss")]
19 pub issuer: Option<HashSet<String>>,
20 #[serde(rename = "sub")]
22 pub subject: Option<String>,
23 #[serde(rename = "aud")]
25 pub audience: Option<HashSet<String>>,
26 #[serde(rename = "exp")]
28 pub expiration_time: Option<u64>,
29 #[serde(rename = "nbf")]
31 pub not_before_time: Option<u64>,
32 #[serde(rename = "iat")]
34 pub issued_at_time: Option<u64>,
35 #[serde(rename = "jti")]
37 pub jwt_id: Option<String>,
38}
39
40impl Default for RegisteredClaims {
41 fn default() -> Self {
43 Self {
44 issuer: None,
45 subject: None,
46 audience: None,
47 expiration_time: Some((Utc::now() + TimeDelta::weeks(1)).timestamp() as u64),
48 not_before_time: None,
49 issued_at_time: None,
50 jwt_id: None,
51 }
52 }
53}
54
55#[derive(Serialize, Deserialize, Clone, Debug)]
57pub struct JwtClaims<CustomClaims> {
58 #[serde(flatten)]
60 pub registered_claims: RegisteredClaims,
61 #[serde(flatten)]
63 pub custom_claims: CustomClaims,
64}
65
66impl<CustomClaims> JwtClaims<CustomClaims> {
67 pub fn new(custom_claims: CustomClaims) -> Self {
69 Self {
70 registered_claims: RegisteredClaims::default(),
71 custom_claims,
72 }
73 }
74
75 pub fn new_with_registered(
77 custom_claims: CustomClaims,
78 registered_claims: RegisteredClaims,
79 ) -> Self {
80 Self {
81 custom_claims,
82 registered_claims,
83 }
84 }
85}
86
87pub struct JsonWebTokenOptions {
89 pub enc_key: EncodingKey,
91 pub dec_key: DecodingKey,
93 pub header: Option<Header>,
95 pub validation: Option<Validation>,
97}
98
99impl Default for JsonWebTokenOptions {
100 fn default() -> Self {
103 use rand::{Rng, distr::Alphanumeric, rng};
104
105 let authentication_secret: String = rng()
106 .sample_iter(&Alphanumeric)
107 .take(60)
108 .map(char::from)
109 .collect();
110 Self {
111 enc_key: EncodingKey::from_secret(authentication_secret.as_bytes()),
112 dec_key: DecodingKey::from_secret(authentication_secret.as_bytes()),
113 header: Some(Header::default()),
114 validation: Some(Validation::default()),
115 }
116 }
117}
118
119#[derive(Clone)]
121pub struct JsonWebToken<P> {
122 enc_key: EncodingKey,
124 dec_key: DecodingKey,
126 pub header: Header,
128 pub validation: Validation,
130 phantom_payload: PhantomData<P>,
131}
132
133impl<P> JsonWebToken<P> {
134 pub fn new_with_options(options: JsonWebTokenOptions) -> Self {
136 let JsonWebTokenOptions {
137 enc_key,
138 dec_key,
139 header,
140 validation,
141 } = options;
142 Self {
143 enc_key,
144 dec_key,
145 header: header.unwrap_or(Header::default()),
146 validation: validation.unwrap_or(Validation::default()),
147 phantom_payload: PhantomData,
148 }
149 }
150}
151
152impl<P> Default for JsonWebToken<P> {
153 fn default() -> Self {
154 Self::new_with_options(JsonWebTokenOptions::default())
155 }
156}
157
158impl<P> CodecService for JsonWebToken<P>
159where
160 P: Serialize + DeserializeOwned + Clone,
161{
162 type Payload = P;
163 fn encode(&self, payload: &Self::Payload) -> Result<Vec<u8>, Error> {
164 let web_token = jsonwebtoken::encode(&self.header, payload, &self.enc_key)
165 .map_err(|e| Error::Codec(format!("{e}")))?;
166 Ok(web_token.as_bytes().to_vec())
167 }
168 fn decode(&self, encoded_value: &[u8]) -> Result<Self::Payload, Error> {
174 let claims = jsonwebtoken::decode::<Self::Payload>(
175 &String::from_utf8_lossy(encoded_value),
176 &self.dec_key,
177 &self.validation,
178 )
179 .map_err(|e| Error::Codec(format!("{e}")))?;
180
181 if self.header != claims.header {
182 return Err(Error::Codec(format!(
183 "Header of the decoded value does not match the one used for encoding."
184 )));
185 }
186
187 Ok(claims.claims)
188 }
189}