1use crate::AuthResult;
2use bon::Builder;
3use jsonwebtoken::{
4 decode, encode, get_current_timestamp, Algorithm, DecodingKey, EncodingKey, Header, TokenData,
5 Validation,
6};
7use serde::{Deserialize, Serialize};
8use serde_json::Value;
9
10#[derive(Debug, Serialize, Deserialize, Clone)]
11pub struct UserClaims {
12 uid: String,
13 exp: usize,
14 claims: Option<Value>,
15}
16
17#[derive(Builder, Debug)]
18pub struct JWT {
19 secret: String,
20 algorithm: Algorithm,
21}
22
23impl JWT {
24 pub fn generate_token(
25 &self,
26 uid: String,
27 expiration: u64,
28 claims: Option<Value>,
29 ) -> AuthResult<String> {
30 let exp = (get_current_timestamp() + expiration) as usize;
31
32 let claims = UserClaims { uid, exp, claims };
33
34 let token = encode(
35 &Header::new(self.algorithm),
36 &claims,
37 &EncodingKey::from_base64_secret(&self.secret)?,
38 )?;
39
40 Ok(token)
41 }
42
43 pub fn validate(&self, token: &str) -> AuthResult<TokenData<UserClaims>> {
44 let mut validate = Validation::new(self.algorithm);
45 validate.leeway = 0;
46
47 Ok(decode::<UserClaims>(
48 token,
49 &DecodingKey::from_base64_secret(&self.secret)?,
50 &validate,
51 )?)
52 }
53}