bitwarden_core/client/
internal.rs1use std::sync::{Arc, 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;
13use crate::{
14 auth::renew::renew_token,
15 client::{encryption_settings::EncryptionSettings, login_method::LoginMethod},
16 key_management::KeyIds,
17 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 #[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) tokens: RwLock<Tokens>,
48 pub(crate) login_method: RwLock<Option<Arc<LoginMethod>>>,
49
50 #[cfg(feature = "internal")]
51 pub(super) flags: RwLock<Flags>,
52
53 #[doc(hidden)]
56 pub(crate) __api_configurations: RwLock<Arc<ApiConfigurations>>,
57
58 #[allow(unused)]
60 pub(crate) external_client: reqwest::Client,
61
62 pub(super) key_store: KeyStore<KeyIds>,
63}
64
65impl InternalClient {
66 #[cfg(feature = "internal")]
67 pub fn load_flags(&self, flags: std::collections::HashMap<String, bool>) {
68 *self.flags.write().expect("RwLock is not poisoned") = Flags::load_from_map(flags);
69 }
70
71 #[cfg(feature = "internal")]
72 pub fn get_flags(&self) -> Flags {
73 self.flags.read().expect("RwLock is not poisoned").clone()
74 }
75
76 #[cfg(feature = "internal")]
77 pub(crate) fn get_login_method(&self) -> Option<Arc<LoginMethod>> {
78 self.login_method
79 .read()
80 .expect("RwLock is not poisoned")
81 .clone()
82 }
83
84 pub fn get_access_token_organization(&self) -> Option<Uuid> {
85 match self
86 .login_method
87 .read()
88 .expect("RwLock is not poisoned")
89 .as_deref()
90 {
91 #[cfg(feature = "secrets")]
92 Some(LoginMethod::ServiceAccount(ServiceAccountLoginMethod::AccessToken {
93 organization_id,
94 ..
95 })) => Some(*organization_id),
96 _ => None,
97 }
98 }
99
100 #[cfg(any(feature = "internal", feature = "secrets"))]
101 pub(crate) fn set_login_method(&self, login_method: LoginMethod) {
102 use log::debug;
103
104 debug! {"setting login method: {:#?}", login_method}
105 *self.login_method.write().expect("RwLock is not poisoned") = Some(Arc::new(login_method));
106 }
107
108 pub(crate) fn set_tokens(&self, token: String, refresh_token: Option<String>, expires_in: u64) {
109 *self.tokens.write().expect("RwLock is not poisoned") = Tokens {
110 access_token: Some(token.clone()),
111 expires_on: Some(Utc::now().timestamp() + expires_in as i64),
112 refresh_token,
113 };
114 let mut guard = self
115 .__api_configurations
116 .write()
117 .expect("RwLock is not poisoned");
118
119 let inner = Arc::make_mut(&mut guard);
120 inner.identity.oauth_access_token = Some(token.clone());
121 inner.api.oauth_access_token = Some(token);
122 }
123
124 #[cfg(feature = "internal")]
125 pub fn is_authed(&self) -> bool {
126 let is_token_set = self
127 .tokens
128 .read()
129 .expect("RwLock is not poisoned")
130 .access_token
131 .is_some();
132 let is_login_method_set = self
133 .login_method
134 .read()
135 .expect("RwLock is not poisoned")
136 .is_some();
137
138 is_token_set || is_login_method_set
139 }
140
141 #[cfg(feature = "internal")]
142 pub fn get_kdf(&self) -> Result<Kdf, NotAuthenticatedError> {
143 match self
144 .login_method
145 .read()
146 .expect("RwLock is not poisoned")
147 .as_deref()
148 {
149 Some(LoginMethod::User(
150 UserLoginMethod::Username { kdf, .. } | UserLoginMethod::ApiKey { kdf, .. },
151 )) => Ok(kdf.clone()),
152 _ => Err(NotAuthenticatedError),
153 }
154 }
155
156 pub async fn get_api_configurations(&self) -> Arc<ApiConfigurations> {
157 renew_token(self).await.ok();
160 self.__api_configurations
161 .read()
162 .expect("RwLock is not poisoned")
163 .clone()
164 }
165
166 #[cfg(feature = "internal")]
167 pub fn get_http_client(&self) -> &reqwest::Client {
168 &self.external_client
169 }
170
171 pub fn get_key_store(&self) -> &KeyStore<KeyIds> {
172 &self.key_store
173 }
174
175 #[cfg(feature = "internal")]
176 pub(crate) fn initialize_user_crypto_master_key(
177 &self,
178 master_key: MasterKey,
179 user_key: EncString,
180 private_key: EncString,
181 ) -> Result<(), EncryptionSettingsError> {
182 let user_key = master_key.decrypt_user_key(user_key)?;
183 EncryptionSettings::new_decrypted_key(user_key, private_key, &self.key_store)?;
184
185 Ok(())
186 }
187
188 #[cfg(feature = "internal")]
189 pub(crate) fn initialize_user_crypto_decrypted_key(
190 &self,
191 user_key: SymmetricCryptoKey,
192 private_key: EncString,
193 ) -> Result<(), EncryptionSettingsError> {
194 EncryptionSettings::new_decrypted_key(user_key, private_key, &self.key_store)?;
195
196 Ok(())
197 }
198
199 #[cfg(feature = "internal")]
200 pub(crate) fn initialize_user_crypto_pin(
201 &self,
202 pin_key: PinKey,
203 pin_protected_user_key: EncString,
204 private_key: EncString,
205 ) -> Result<(), EncryptionSettingsError> {
206 let decrypted_user_key = pin_key.decrypt_user_key(pin_protected_user_key)?;
207 self.initialize_user_crypto_decrypted_key(decrypted_user_key, private_key)
208 }
209
210 #[cfg(feature = "secrets")]
211 pub(crate) fn initialize_crypto_single_org_key(
212 &self,
213 organization_id: Uuid,
214 key: SymmetricCryptoKey,
215 ) {
216 EncryptionSettings::new_single_org_key(organization_id, key, &self.key_store);
217 }
218
219 #[cfg(feature = "internal")]
220 pub fn initialize_org_crypto(
221 &self,
222 org_keys: Vec<(Uuid, UnsignedSharedKey)>,
223 ) -> Result<(), EncryptionSettingsError> {
224 EncryptionSettings::set_org_keys(org_keys, &self.key_store)
225 }
226}