1use hmac::digest::KeyInit;
2use jwt::{SignWithKey, VerifyWithKey};
3use serde::{Deserialize, Serialize, de::DeserializeOwned};
4
5#[derive(Deserialize, Serialize)]
6pub struct BasePayload {
7 #[serde(rename = "iss")]
8 pub issuer: String,
9 #[serde(rename = "sub")]
10 pub subject: Option<String>,
11 #[serde(rename = "aud")]
12 pub audience: Vec<String>,
13 #[serde(rename = "exp")]
14 pub expiration_time: Option<i64>,
15 #[serde(rename = "nbf")]
16 pub not_before: Option<i64>,
17 #[serde(rename = "iat")]
18 pub issued_at: Option<i64>,
19 #[serde(rename = "jti")]
20 pub jwt_id: String,
21}
22
23impl BasePayload {
24 pub fn validate(&self) -> bool {
25 let now = chrono::Utc::now().timestamp();
26
27 if let Some(exp) = self.expiration_time {
28 if exp < now {
29 return false;
30 }
31 } else {
32 return false;
33 }
34
35 if let Some(nbf) = self.not_before
36 && nbf > now
37 {
38 return false;
39 }
40
41 if let Some(iat) = self.issued_at {
42 if iat > now {
43 return false;
44 }
45 } else {
46 return false;
47 }
48
49 true
50 }
51}
52
53pub struct Jwt {
54 key: hmac::Hmac<sha2::Sha256>,
55}
56
57impl Jwt {
58 pub fn new(env: &crate::env::Env) -> Self {
59 Self {
60 key: hmac::Hmac::new_from_slice(env.app_encryption_key.as_bytes()).unwrap(),
61 }
62 }
63
64 #[inline]
65 pub fn verify<T: DeserializeOwned>(&self, token: &str) -> Result<T, jwt::Error> {
66 token.verify_with_key(&self.key)
67 }
68
69 #[inline]
70 pub fn create<T: Serialize>(&self, payload: &T) -> Result<String, jwt::Error> {
71 payload.sign_with_key(&self.key)
72 }
73
74 #[inline]
75 pub fn create_custom<T: Serialize>(
76 &self,
77 key: &[u8],
78 payload: &T,
79 ) -> Result<String, jwt::Error> {
80 payload.sign_with_key(&hmac::Hmac::<sha2::Sha256>::new_from_slice(key)?)
81 }
82}