Skip to main content

bitwarden_core/auth/
renew.rs

1#[cfg(feature = "secrets")]
2use bitwarden_crypto::KeyStore;
3
4use super::login::LoginError;
5use crate::{
6    NotAuthenticatedError,
7    auth::api::{request::ApiTokenRequest, response::IdentityTokenResponse},
8    client::UserLoginMethod,
9};
10#[cfg(feature = "secrets")]
11use crate::{
12    auth::api::request::AccessTokenRequest,
13    client::ServiceAccountLoginMethod,
14    key_management::KeyIds,
15    key_management::SymmetricKeyId,
16    secrets_manager::state::{self, ClientState},
17};
18
19pub async fn renew_pm_token_sdk_managed(
20    refresh_token: Option<String>,
21    login_method: &UserLoginMethod,
22    identity_config: bitwarden_api_api::Configuration,
23) -> Result<(String, Option<String>, u64), LoginError> {
24    let res = match login_method {
25        UserLoginMethod::Username { client_id, .. } => {
26            let refresh = refresh_token.ok_or(NotAuthenticatedError)?;
27
28            crate::auth::api::request::RenewTokenRequest::new(refresh, client_id.to_owned())
29                .send(&identity_config)
30                .await?
31        }
32        UserLoginMethod::ApiKey {
33            client_id,
34            client_secret,
35            ..
36        } => {
37            ApiTokenRequest::new(client_id, client_secret)
38                .send(&identity_config)
39                .await?
40        }
41    };
42
43    match res {
44        IdentityTokenResponse::Refreshed(r) => Ok((r.access_token, r.refresh_token, r.expires_in)),
45        IdentityTokenResponse::Authenticated(r) => {
46            Ok((r.access_token, r.refresh_token, r.expires_in))
47        }
48        _ => {
49            // We should never get here
50            Err(LoginError::InvalidResponse)
51        }
52    }
53}
54
55#[cfg(feature = "secrets")]
56pub async fn renew_sm_token_sdk_managed(
57    login_method: &ServiceAccountLoginMethod,
58    identity_config: bitwarden_api_api::Configuration,
59    key_store: KeyStore<KeyIds>,
60) -> Result<(String, Option<String>, u64), LoginError> {
61    let res = match login_method {
62        ServiceAccountLoginMethod::AccessToken {
63            access_token,
64            state_file,
65            ..
66        } => {
67            let result =
68                AccessTokenRequest::new(access_token.access_token_id, &access_token.client_secret)
69                    .send(&identity_config)
70                    .await?;
71
72            if let (IdentityTokenResponse::Payload(r), Some(state_file)) = (&result, state_file) {
73                let ctx = key_store.context();
74                #[allow(deprecated)]
75                if let Ok(enc_key) = ctx.dangerous_get_symmetric_key(SymmetricKeyId::User) {
76                    let state = ClientState::new(r.access_token.clone(), enc_key.to_base64());
77                    _ = state::set(state_file, access_token, state);
78                }
79            }
80
81            result
82        }
83    };
84
85    match res {
86        IdentityTokenResponse::Refreshed(r) => Ok((r.access_token, r.refresh_token, r.expires_in)),
87        IdentityTokenResponse::Authenticated(r) => {
88            Ok((r.access_token, r.refresh_token, r.expires_in))
89        }
90        IdentityTokenResponse::Payload(r) => Ok((r.access_token, r.refresh_token, r.expires_in)),
91        _ => {
92            // We should never get here
93            Err(LoginError::InvalidResponse)
94        }
95    }
96}