bitwarden_core/client/
internal.rs

1use std::sync::{Arc, OnceLock, RwLock};
2
3use bitwarden_crypto::KeyStore;
4#[cfg(any(feature = "internal", feature = "secrets"))]
5use bitwarden_crypto::SymmetricCryptoKey;
6#[cfg(feature = "internal")]
7use bitwarden_crypto::{EncString, Kdf, MasterKey, PinKey, UnsignedSharedKey};
8use chrono::Utc;
9use uuid::Uuid;
10
11#[cfg(feature = "secrets")]
12use super::login_method::ServiceAccountLoginMethod;
13#[cfg(any(feature = "internal", feature = "secrets"))]
14use crate::client::encryption_settings::EncryptionSettings;
15use crate::{
16    auth::renew::renew_token, client::login_method::LoginMethod, error::UserIdAlreadySetError,
17    key_management::KeyIds, DeviceType,
18};
19#[cfg(feature = "internal")]
20use crate::{
21    client::encryption_settings::EncryptionSettingsError,
22    client::{flags::Flags, login_method::UserLoginMethod},
23    error::NotAuthenticatedError,
24};
25
26#[derive(Debug, Clone)]
27pub struct ApiConfigurations {
28    pub identity: bitwarden_api_identity::apis::configuration::Configuration,
29    pub api: bitwarden_api_api::apis::configuration::Configuration,
30    pub device_type: DeviceType,
31}
32
33#[derive(Debug, Default, Clone)]
34pub(crate) struct Tokens {
35    // These two fields are always written to, but they are not read
36    // from the secrets manager SDK.
37    #[cfg_attr(not(feature = "internal"), allow(dead_code))]
38    access_token: Option<String>,
39    pub(crate) expires_on: Option<i64>,
40
41    #[cfg_attr(not(feature = "internal"), allow(dead_code))]
42    pub(crate) refresh_token: Option<String>,
43}
44
45#[derive(Debug)]
46pub struct InternalClient {
47    pub(crate) user_id: OnceLock<Uuid>,
48    pub(crate) tokens: RwLock<Tokens>,
49    pub(crate) login_method: RwLock<Option<Arc<LoginMethod>>>,
50
51    #[cfg(feature = "internal")]
52    pub(super) flags: RwLock<Flags>,
53
54    /// Use Client::get_api_configurations().await to access this.
55    /// It should only be used directly in renew_token
56    #[doc(hidden)]
57    pub(crate) __api_configurations: RwLock<Arc<ApiConfigurations>>,
58
59    /// Reqwest client useable for external integrations like email forwarders, HIBP.
60    #[allow(unused)]
61    pub(crate) external_client: reqwest::Client,
62
63    pub(super) key_store: KeyStore<KeyIds>,
64}
65
66impl InternalClient {
67    #[cfg(feature = "internal")]
68    pub fn load_flags(&self, flags: std::collections::HashMap<String, bool>) {
69        *self.flags.write().expect("RwLock is not poisoned") = Flags::load_from_map(flags);
70    }
71
72    #[cfg(feature = "internal")]
73    pub fn get_flags(&self) -> Flags {
74        self.flags.read().expect("RwLock is not poisoned").clone()
75    }
76
77    #[cfg(feature = "internal")]
78    pub(crate) fn get_login_method(&self) -> Option<Arc<LoginMethod>> {
79        self.login_method
80            .read()
81            .expect("RwLock is not poisoned")
82            .clone()
83    }
84
85    pub fn get_access_token_organization(&self) -> Option<Uuid> {
86        match self
87            .login_method
88            .read()
89            .expect("RwLock is not poisoned")
90            .as_deref()
91        {
92            #[cfg(feature = "secrets")]
93            Some(LoginMethod::ServiceAccount(ServiceAccountLoginMethod::AccessToken {
94                organization_id,
95                ..
96            })) => Some(*organization_id),
97            _ => None,
98        }
99    }
100
101    #[cfg(any(feature = "internal", feature = "secrets"))]
102    pub(crate) fn set_login_method(&self, login_method: LoginMethod) {
103        use log::debug;
104
105        debug! {"setting login method: {:#?}", login_method}
106        *self.login_method.write().expect("RwLock is not poisoned") = Some(Arc::new(login_method));
107    }
108
109    pub(crate) fn set_tokens(&self, token: String, refresh_token: Option<String>, expires_in: u64) {
110        *self.tokens.write().expect("RwLock is not poisoned") = Tokens {
111            access_token: Some(token.clone()),
112            expires_on: Some(Utc::now().timestamp() + expires_in as i64),
113            refresh_token,
114        };
115        let mut guard = self
116            .__api_configurations
117            .write()
118            .expect("RwLock is not poisoned");
119
120        let inner = Arc::make_mut(&mut guard);
121        inner.identity.oauth_access_token = Some(token.clone());
122        inner.api.oauth_access_token = Some(token);
123    }
124
125    #[cfg(feature = "internal")]
126    pub fn is_authed(&self) -> bool {
127        let is_token_set = self
128            .tokens
129            .read()
130            .expect("RwLock is not poisoned")
131            .access_token
132            .is_some();
133        let is_login_method_set = self
134            .login_method
135            .read()
136            .expect("RwLock is not poisoned")
137            .is_some();
138
139        is_token_set || is_login_method_set
140    }
141
142    #[cfg(feature = "internal")]
143    pub fn get_kdf(&self) -> Result<Kdf, NotAuthenticatedError> {
144        match self
145            .login_method
146            .read()
147            .expect("RwLock is not poisoned")
148            .as_deref()
149        {
150            Some(LoginMethod::User(
151                UserLoginMethod::Username { kdf, .. } | UserLoginMethod::ApiKey { kdf, .. },
152            )) => Ok(kdf.clone()),
153            _ => Err(NotAuthenticatedError),
154        }
155    }
156
157    pub async fn get_api_configurations(&self) -> Arc<ApiConfigurations> {
158        // At the moment we ignore the error result from the token renewal, if it fails,
159        // the token will end up expiring and the next operation is going to fail anyway.
160        renew_token(self).await.ok();
161        self.__api_configurations
162            .read()
163            .expect("RwLock is not poisoned")
164            .clone()
165    }
166
167    #[cfg(feature = "internal")]
168    pub fn get_http_client(&self) -> &reqwest::Client {
169        &self.external_client
170    }
171
172    pub fn get_key_store(&self) -> &KeyStore<KeyIds> {
173        &self.key_store
174    }
175
176    pub fn init_user_id(&self, user_id: Uuid) -> Result<(), UserIdAlreadySetError> {
177        self.user_id.set(user_id).map_err(|_| UserIdAlreadySetError)
178    }
179
180    pub fn get_user_id(&self) -> Option<Uuid> {
181        self.user_id.get().copied()
182    }
183
184    #[cfg(feature = "internal")]
185    pub(crate) fn initialize_user_crypto_master_key(
186        &self,
187        master_key: MasterKey,
188        user_key: EncString,
189        private_key: EncString,
190    ) -> Result<(), EncryptionSettingsError> {
191        let user_key = master_key.decrypt_user_key(user_key)?;
192        EncryptionSettings::new_decrypted_key(user_key, private_key, &self.key_store)?;
193
194        Ok(())
195    }
196
197    #[cfg(feature = "internal")]
198    pub(crate) fn initialize_user_crypto_decrypted_key(
199        &self,
200        user_key: SymmetricCryptoKey,
201        private_key: EncString,
202    ) -> Result<(), EncryptionSettingsError> {
203        EncryptionSettings::new_decrypted_key(user_key, private_key, &self.key_store)?;
204
205        Ok(())
206    }
207
208    #[cfg(feature = "internal")]
209    pub(crate) fn initialize_user_crypto_pin(
210        &self,
211        pin_key: PinKey,
212        pin_protected_user_key: EncString,
213        private_key: EncString,
214    ) -> Result<(), EncryptionSettingsError> {
215        let decrypted_user_key = pin_key.decrypt_user_key(pin_protected_user_key)?;
216        self.initialize_user_crypto_decrypted_key(decrypted_user_key, private_key)
217    }
218
219    #[cfg(feature = "secrets")]
220    pub(crate) fn initialize_crypto_single_org_key(
221        &self,
222        organization_id: Uuid,
223        key: SymmetricCryptoKey,
224    ) {
225        EncryptionSettings::new_single_org_key(organization_id, key, &self.key_store);
226    }
227
228    #[cfg(feature = "internal")]
229    pub fn initialize_org_crypto(
230        &self,
231        org_keys: Vec<(Uuid, UnsignedSharedKey)>,
232    ) -> Result<(), EncryptionSettingsError> {
233        EncryptionSettings::set_org_keys(org_keys, &self.key_store)
234    }
235}