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}