shared/
jwt.rs

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}