1use crate::error::AuthError;
2use jsonwebtoken::{decode, encode, DecodingKey, EncodingKey, Header, Validation};
3use password_auth::verify_password;
4use rand::distr::Alphanumeric;
5use rand::Rng;
6use scouter_sql::sql::schema::User;
7use serde::{Deserialize, Serialize};
8use std::time::{SystemTime, UNIX_EPOCH};
9
10#[derive(Debug, Serialize, Deserialize)]
11pub struct Claims {
12 pub sub: String,
13 exp: usize,
14 pub permissions: Vec<String>,
15 pub group_permissions: Vec<String>,
16 salt: String,
17}
18
19pub struct AuthManager {
20 jwt_secret: String,
21 refresh_secret: String,
22}
23impl AuthManager {
24 pub fn new(jwt_secret: &str, refresh_secret: &str) -> Self {
25 Self {
26 jwt_secret: jwt_secret.to_string(),
27 refresh_secret: refresh_secret.to_string(),
28 }
29 }
30
31 fn generate_salt(&self) -> String {
32 rand::rng()
33 .sample_iter(&Alphanumeric)
34 .take(16)
35 .map(char::from)
36 .collect()
37 }
38
39 pub fn generate_jwt(&self, user: &User) -> String {
40 let expiration = SystemTime::now()
41 .duration_since(UNIX_EPOCH)
42 .unwrap()
43 .as_secs()
44 + 3600; let claims = Claims {
47 sub: user.username.clone(),
48 exp: expiration as usize,
49 permissions: user.permissions.clone(),
50 group_permissions: user.group_permissions.clone(),
51 salt: self.generate_salt(),
52 };
53
54 encode(
55 &Header::default(),
56 &claims,
57 &EncodingKey::from_secret(self.jwt_secret.as_ref()),
58 )
59 .unwrap()
60 }
61
62 pub fn generate_refresh_token(&self, user: &User) -> String {
63 let expiration = SystemTime::now()
64 .duration_since(UNIX_EPOCH)
65 .unwrap()
66 .as_secs()
67 + 86400; let claims = Claims {
70 sub: user.username.clone(),
71 exp: expiration as usize,
72 permissions: user.permissions.clone(),
73 group_permissions: user.group_permissions.clone(),
74 salt: self.generate_salt(),
75 };
76
77 encode(
78 &Header::default(),
79 &claims,
80 &EncodingKey::from_secret(self.refresh_secret.as_ref()),
81 )
82 .unwrap()
83 }
84
85 pub fn validate_jwt(&self, token: &str) -> Result<Claims, jsonwebtoken::errors::Error> {
86 let token_data = decode::<Claims>(
87 token,
88 &DecodingKey::from_secret(self.jwt_secret.as_ref()),
89 &Validation::default(),
90 )?;
91 Ok(token_data.claims)
92 }
93
94 pub fn decode_jwt_without_validation(
95 &self,
96 token: &str,
97 ) -> Result<Claims, jsonwebtoken::errors::Error> {
98 let mut validation = Validation::default();
99 validation.insecure_disable_signature_validation();
100 let token_data = decode::<Claims>(
101 token,
102 &DecodingKey::from_secret(self.jwt_secret.as_ref()),
103 &validation,
104 )?;
105
106 Ok(token_data.claims)
107 }
108
109 pub fn validate_refresh_token(
110 &self,
111 token: &str,
112 ) -> Result<Claims, jsonwebtoken::errors::Error> {
113 let token_data = decode::<Claims>(
114 token,
115 &DecodingKey::from_secret(self.refresh_secret.as_ref()),
116 &Validation::default(),
117 )?;
118 Ok(token_data.claims)
119 }
120
121 pub fn validate_user(&self, user: &User, password: &str) -> Result<(), AuthError> {
122 verify_password(password, &user.password_hash).map_err(AuthError::InvalidPassword)
123 }
124}