karbon_framework/security/
jwt.rs1use chrono::Utc;
2use jsonwebtoken::{decode, encode, DecodingKey, EncodingKey, Header, Validation};
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct Claims {
8 pub sub: String,
10 pub username: String,
12 pub roles: Vec<String>,
14 #[serde(default, skip_serializing_if = "Option::is_none")]
16 pub user_id: Option<i64>,
17 #[serde(default, skip_serializing_if = "Option::is_none")]
19 pub user_uuid: Option<String>,
20 #[serde(default, skip_serializing_if = "Option::is_none")]
22 pub aud: Option<String>,
23 pub exp: i64,
25 pub iat: i64,
27}
28
29#[derive(Clone)]
31pub struct JwtManager {
32 encoding_key: EncodingKey,
33 decoding_key: DecodingKey,
34 expiration: i64,
35}
36
37impl JwtManager {
38 pub fn new(secret: &str, expiration: i64) -> Self {
40 Self {
41 encoding_key: EncodingKey::from_secret(secret.as_bytes()),
42 decoding_key: DecodingKey::from_secret(secret.as_bytes()),
43 expiration,
44 }
45 }
46
47 pub fn generate(&self, sub: &str, username: &str, roles: Vec<String>) -> Result<String, jsonwebtoken::errors::Error> {
49 self.generate_full(sub, username, roles, None, None, None)
50 }
51
52 pub fn generate_full(
54 &self,
55 sub: &str,
56 username: &str,
57 roles: Vec<String>,
58 user_id: Option<i64>,
59 user_uuid: Option<String>,
60 aud: Option<String>,
61 ) -> Result<String, jsonwebtoken::errors::Error> {
62 let now = Utc::now().timestamp();
63 let claims = Claims {
64 sub: sub.to_string(),
65 username: username.to_string(),
66 roles,
67 user_id,
68 user_uuid,
69 aud,
70 exp: now + self.expiration,
71 iat: now,
72 };
73
74 encode(&Header::default(), &claims, &self.encoding_key)
75 }
76
77 pub fn verify(&self, token: &str) -> Result<Claims, jsonwebtoken::errors::Error> {
79 let mut validation = Validation::default();
80 validation.validate_aud = false;
81 let token_data = decode::<Claims>(token, &self.decoding_key, &validation)?;
82 Ok(token_data.claims)
83 }
84
85 pub fn generate_refresh_token() -> String {
89 super::Crypto::random_token(48)
90 }
91}