1use base64::{Engine as _, engine::general_purpose};
2use serde::{Deserialize, Serialize};
3use uuid::Uuid;
4
5#[derive(Debug, Serialize, Deserialize)]
6pub struct TokenDetails {
7 pub token: Option<String>,
8 pub token_uuid: uuid::Uuid,
9 pub user_id: uuid::Uuid,
10 pub expires_in: Option<i64>,
11}
12
13#[derive(Debug, Serialize, Deserialize, Clone)]
14pub struct TokenClaims {
15 pub sub: String,
16 pub token_uuid: String,
17 pub exp: i64,
18 pub iat: i64,
19 pub nbf: i64,
20}
21
22pub fn generate_jwt_token(
23 user_id: uuid::Uuid,
24 ttl: i64,
25 private_key: &str,
26) -> Result<TokenDetails, jsonwebtoken::errors::Error> {
27 generate_jwt_token_with_uuid(user_id, Uuid::new_v4(), ttl, private_key)
28}
29
30pub fn generate_jwt_token_with_uuid(
31 user_id: uuid::Uuid,
32 token_uuid: uuid::Uuid,
33 ttl: i64,
34 private_key: &str,
35) -> Result<TokenDetails, jsonwebtoken::errors::Error> {
36 let bytes_private_key = general_purpose::STANDARD.decode(private_key).unwrap();
37 let decoded_private_key = String::from_utf8(bytes_private_key).unwrap();
38
39 let now = chrono::Utc::now();
40 let mut token_details = TokenDetails {
41 user_id,
42 token_uuid,
43 expires_in: Some((now + chrono::Duration::minutes(ttl)).timestamp()),
44 token: None,
45 };
46
47 let claims = TokenClaims {
48 sub: token_details.user_id.to_string(),
49 token_uuid: token_details.token_uuid.to_string(),
50 exp: token_details.expires_in.unwrap(),
51 iat: now.timestamp(),
52 nbf: now.timestamp(),
53 };
54
55 let header = jsonwebtoken::Header::new(jsonwebtoken::Algorithm::RS256);
56 let token = jsonwebtoken::encode(
57 &header,
58 &claims,
59 &jsonwebtoken::EncodingKey::from_rsa_pem(decoded_private_key.as_bytes())?,
60 )?;
61 token_details.token = Some(token);
62 Ok(token_details)
63}
64
65pub fn verify_jwt_token(
66 public_key: &str,
67 token: &str,
68) -> Result<TokenDetails, jsonwebtoken::errors::Error> {
69 let bytes_public_key = general_purpose::STANDARD.decode(public_key).unwrap();
70 let decoded_public_key = String::from_utf8(bytes_public_key).unwrap();
71
72 let validation = jsonwebtoken::Validation::new(jsonwebtoken::Algorithm::RS256);
73
74 let decoded = jsonwebtoken::decode::<TokenClaims>(
75 token,
76 &jsonwebtoken::DecodingKey::from_rsa_pem(decoded_public_key.as_bytes())?,
77 &validation,
78 )?;
79
80 let user_id = Uuid::parse_str(decoded.claims.sub.as_str()).unwrap();
81 let token_uuid = Uuid::parse_str(decoded.claims.token_uuid.as_str()).unwrap();
82
83 Ok(TokenDetails {
84 token: None,
85 token_uuid,
86 user_id,
87 expires_in: None,
88 })
89}