Skip to main content

shared/
jwt.rs

1use jsonwebtoken::{Algorithm, DecodingKey, EncodingKey, Header, Validation};
2use serde::{Deserialize, Serialize, de::DeserializeOwned};
3
4#[derive(Deserialize, Serialize)]
5pub struct BasePayload {
6    pub scope: compact_str::CompactString,
7
8    #[serde(rename = "iss")]
9    pub issuer: compact_str::CompactString,
10    #[serde(rename = "sub")]
11    pub subject: Option<compact_str::CompactString>,
12    #[serde(rename = "aud")]
13    pub audience: Vec<compact_str::CompactString>,
14    #[serde(rename = "exp")]
15    pub expiration_time: Option<i64>,
16    #[serde(rename = "nbf")]
17    pub not_before: Option<i64>,
18    #[serde(rename = "iat")]
19    pub issued_at: Option<i64>,
20    #[serde(rename = "jti")]
21    pub jwt_id: compact_str::CompactString,
22}
23
24impl BasePayload {
25    pub fn validate(&self, scope: Option<&str>) -> bool {
26        let now = chrono::Utc::now().timestamp();
27        if let Some(exp) = self.expiration_time {
28            if exp < now {
29                return false;
30            }
31        } else {
32            return false;
33        }
34        if let Some(nbf) = self.not_before
35            && nbf > now
36        {
37            return false;
38        }
39        if let Some(iat) = self.issued_at {
40            if iat > now {
41                return false;
42            }
43        } else {
44            return false;
45        }
46
47        if let Some(scope) = scope
48            && self.scope != scope
49        {
50            return false;
51        }
52
53        true
54    }
55}
56
57pub struct Jwt {
58    encoding_key: EncodingKey,
59    decoding_key: DecodingKey,
60}
61
62impl Jwt {
63    pub fn new(env: &crate::env::Env) -> Self {
64        let secret = env.app_encryption_key.as_bytes();
65        Self {
66            encoding_key: EncodingKey::from_secret(secret),
67            decoding_key: DecodingKey::from_secret(secret),
68        }
69    }
70
71    #[inline]
72    pub fn verify<T: DeserializeOwned>(
73        &self,
74        token: &str,
75    ) -> Result<T, jsonwebtoken::errors::Error> {
76        let mut validation = Validation::new(Algorithm::HS256);
77        validation.validate_exp = false;
78        validation.validate_aud = false;
79        validation.required_spec_claims.clear();
80        let data = jsonwebtoken::decode::<T>(token, &self.decoding_key, &validation)?;
81        Ok(data.claims)
82    }
83
84    #[inline]
85    pub fn create<T: Serialize>(&self, payload: &T) -> Result<String, jsonwebtoken::errors::Error> {
86        jsonwebtoken::encode(&Header::new(Algorithm::HS256), payload, &self.encoding_key)
87    }
88
89    #[inline]
90    pub fn create_custom<T: Serialize>(
91        &self,
92        key: &[u8],
93        payload: &T,
94    ) -> Result<String, jsonwebtoken::errors::Error> {
95        let encoding_key = EncodingKey::from_secret(key);
96        jsonwebtoken::encode(&Header::new(Algorithm::HS256), payload, &encoding_key)
97    }
98}