myc_http_tools/functions/
encode_jwt.rs

1use crate::{
2    dtos::claims::Claims, models::internal_auth_config::InternalOauthConfig,
3    settings::MYCELIUM_PROVIDER_KEY, utils::HttpJsonResponse,
4};
5
6use actix_web::HttpResponse;
7use chrono::{Duration, Utc};
8use jsonwebtoken::{encode, Algorithm, EncodingKey, Header};
9use myc_core::{domain::dtos::user::User, models::AccountLifeCycle};
10use tracing::error;
11
12/// Encode a user into a JWT token
13pub async fn encode_jwt(
14    user: User,
15    auth_config: InternalOauthConfig,
16    core_config: AccountLifeCycle,
17    is_temporary: bool,
18) -> Result<(String, Duration), HttpResponse> {
19    let expires_in = match match is_temporary {
20        true => auth_config.tmp_expires_in,
21        false => auth_config.jwt_expires_in,
22    }
23    .async_get_or_error()
24    .await
25    {
26        Ok(exp) => exp,
27        Err(err) => {
28            error!("Could not get token expiration: {err}");
29
30            return Err(HttpResponse::InternalServerError().json(
31                HttpJsonResponse::new_message(
32                    "Could not get token expiration.".to_string(),
33                ),
34            ));
35        }
36    };
37
38    let duration = chrono::Duration::seconds(expires_in);
39
40    let expiration = match Utc::now().checked_add_signed(duration) {
41        Some(exp) => exp.timestamp(),
42        None => {
43            return Err(HttpResponse::InternalServerError().json(
44                HttpJsonResponse::new_message(
45                    "Could not calculate token expiration.".to_string(),
46                ),
47            ));
48        }
49    };
50
51    let claims = Claims {
52        iat: Utc::now().timestamp(),
53        sub: match user.id.to_owned() {
54            Some(id) => id.to_string(),
55            None => "".to_string(),
56        },
57        email: user.email.email(),
58        exp: expiration,
59        iss: MYCELIUM_PROVIDER_KEY.to_string(),
60        aud: core_config
61            .domain_url
62            .ok_or(core_config.domain_name)
63            .map_err(|err| {
64                error!("Could not get domain URL: {err:?}");
65
66                HttpResponse::InternalServerError().json(
67                    HttpJsonResponse::new_message(
68                        "Unexpected error on build JWT claims".to_string(),
69                    ),
70                )
71            })?
72            .async_get_or_error()
73            .await
74            .map_err(|err| {
75                error!("Could not get domain URL: {err:?}");
76
77                HttpResponse::InternalServerError().json(
78                    HttpJsonResponse::new_message(
79                        "Unexpected error on build JWT claims".to_string(),
80                    ),
81                )
82            })?,
83    };
84
85    let header = Header::new(Algorithm::HS512);
86
87    let secret = match auth_config.jwt_secret.async_get_or_error().await {
88        Ok(key) => key,
89        Err(_) => {
90            return Err(HttpResponse::InternalServerError().json(
91                HttpJsonResponse::new_message(
92                    "Could not get token secret key.".to_string(),
93                ),
94            ));
95        }
96    };
97
98    match encode(
99        &header,
100        &claims,
101        &EncodingKey::from_secret(secret.as_bytes()),
102    ) {
103        Ok(token) => Ok((token, duration)),
104        Err(err) => Err(HttpResponse::InternalServerError()
105            .json(HttpJsonResponse::new_message(err.to_string()))),
106    }
107}