1
use base64::{Engine as _, engine::general_purpose};
2
use serde::{Deserialize, Serialize};
3
use uuid::Uuid;
4

            
5
#[derive(Debug, Serialize, Deserialize)]
6
pub 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)]
14
pub 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

            
22
3
pub fn generate_jwt_token(
23
3
    user_id: uuid::Uuid,
24
3
    ttl: i64,
25
3
    private_key: &str,
26
3
) -> Result<TokenDetails, jsonwebtoken::errors::Error> {
27
3
    generate_jwt_token_with_uuid(user_id, Uuid::new_v4(), ttl, private_key)
28
3
}
29

            
30
6
pub fn generate_jwt_token_with_uuid(
31
6
    user_id: uuid::Uuid,
32
6
    token_uuid: uuid::Uuid,
33
6
    ttl: i64,
34
6
    private_key: &str,
35
6
) -> Result<TokenDetails, jsonwebtoken::errors::Error> {
36
6
    let bytes_private_key = general_purpose::STANDARD.decode(private_key).unwrap();
37
6
    let decoded_private_key = String::from_utf8(bytes_private_key).unwrap();
38

            
39
6
    let now = chrono::Utc::now();
40
6
    let mut token_details = TokenDetails {
41
6
        user_id,
42
6
        token_uuid,
43
6
        expires_in: Some((now + chrono::Duration::minutes(ttl)).timestamp()),
44
6
        token: None,
45
6
    };
46

            
47
6
    let claims = TokenClaims {
48
6
        sub: token_details.user_id.to_string(),
49
6
        token_uuid: token_details.token_uuid.to_string(),
50
6
        exp: token_details.expires_in.unwrap(),
51
6
        iat: now.timestamp(),
52
6
        nbf: now.timestamp(),
53
6
    };
54

            
55
6
    let header = jsonwebtoken::Header::new(jsonwebtoken::Algorithm::RS256);
56
6
    let token = jsonwebtoken::encode(
57
6
        &header,
58
6
        &claims,
59
6
        &jsonwebtoken::EncodingKey::from_rsa_pem(decoded_private_key.as_bytes())?,
60
    )?;
61
6
    token_details.token = Some(token);
62
6
    Ok(token_details)
63
6
}
64

            
65
5
pub fn verify_jwt_token(
66
5
    public_key: &str,
67
5
    token: &str,
68
5
) -> Result<TokenDetails, jsonwebtoken::errors::Error> {
69
5
    let bytes_public_key = general_purpose::STANDARD.decode(public_key).unwrap();
70
5
    let decoded_public_key = String::from_utf8(bytes_public_key).unwrap();
71

            
72
5
    let validation = jsonwebtoken::Validation::new(jsonwebtoken::Algorithm::RS256);
73

            
74
4
    let decoded = jsonwebtoken::decode::<TokenClaims>(
75
5
        token,
76
5
        &jsonwebtoken::DecodingKey::from_rsa_pem(decoded_public_key.as_bytes())?,
77
4
        &validation,
78
    )?;
79

            
80
4
    let user_id = Uuid::parse_str(decoded.claims.sub.as_str()).unwrap();
81
4
    let token_uuid = Uuid::parse_str(decoded.claims.token_uuid.as_str()).unwrap();
82

            
83
4
    Ok(TokenDetails {
84
4
        token: None,
85
4
        token_uuid,
86
4
        user_id,
87
4
        expires_in: None,
88
4
    })
89
5
}