light_openid/
token_refresher.rs1use crate::client::OpenIDClient;
2use crate::errors::{OpenIdError, Res};
3use crate::primitives::OpenIDTokenResponse;
4use crate::utils::time_utils::time;
5use std::time::Duration;
6
7#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
9pub struct TokenRefresher {
10 pub token: OpenIDTokenResponse,
11 expires_at: u64,
12}
13
14impl TokenRefresher {
15 pub fn from_token(token: OpenIDTokenResponse) -> Option<Self> {
17 Some(Self {
18 expires_at: time() + token.expires_in?,
19 token,
20 })
21 }
22
23 pub fn should_refresh(&self) -> bool {
26 self.should_refresh_if_expire_before(Duration::from_secs(
27 self.token.expires_in.unwrap_or(15 * 60) / 4,
28 ))
29 }
30
31 pub fn should_refresh_if_expire_before(&self, duration: Duration) -> bool {
36 if self.token.refresh_token.is_none() {
37 return false;
38 }
39
40 self.expires_at - duration.as_secs() < time()
41 }
42
43 pub fn is_expired(&self) -> bool {
45 self.expires_at <= time()
46 }
47
48 pub async fn refresh(&mut self, client: &OpenIDClient) -> Res<()> {
50 let Some(refresh_token) = &self.token.refresh_token else {
51 return Err(OpenIdError::MissingRefreshToken);
52 };
53
54 let (token, _) = client
55 .request_token_from_refresh_token(refresh_token)
56 .await?;
57
58 self.token.access_token = token.access_token;
60 self.token.token_type = token.token_type;
61
62 self.expires_at = time() + token.expires_in.unwrap_or(3600);
63 self.token.expires_in = token.expires_in;
64
65 if let Some(new) = token.refresh_token {
66 self.token.refresh_token = Some(new);
67 }
68
69 if let Some(new) = token.id_token {
70 self.token.id_token = Some(new);
71 }
72
73 Ok(())
74 }
75}