bitwarden_core/auth/
auth_client.rs

1#[cfg(feature = "internal")]
2use bitwarden_crypto::{
3    CryptoError, DeviceKey, EncString, Kdf, TrustDeviceResponse, UnsignedSharedKey,
4};
5
6#[cfg(feature = "secrets")]
7use crate::auth::login::{login_access_token, AccessTokenLoginRequest, AccessTokenLoginResponse};
8#[cfg(feature = "internal")]
9use crate::{
10    auth::{
11        auth_request::{approve_auth_request, new_auth_request, ApproveAuthRequestError},
12        key_connector::{make_key_connector_keys, KeyConnectorResponse},
13        login::{
14            login_api_key, login_password, send_two_factor_email, ApiKeyLoginRequest,
15            ApiKeyLoginResponse, NewAuthRequestResponse, PasswordLoginRequest,
16            PasswordLoginResponse, PreloginError, TwoFactorEmailError, TwoFactorEmailRequest,
17        },
18        password::{
19            password_strength, satisfies_policy, validate_password, validate_password_user_key,
20            MasterPasswordPolicyOptions,
21        },
22        pin::validate_pin,
23        register::make_register_keys,
24        tde::{make_register_tde_keys, RegisterTdeKeyResponse},
25        AuthRequestResponse, AuthValidateError, RegisterKeyResponse,
26    },
27    client::encryption_settings::EncryptionSettingsError,
28};
29use crate::{
30    auth::{login::LoginError, renew::renew_token},
31    Client,
32};
33
34#[allow(missing_docs)]
35pub struct AuthClient {
36    pub(crate) client: crate::Client,
37}
38
39impl AuthClient {
40    #[allow(missing_docs)]
41    pub async fn renew_token(&self) -> Result<(), LoginError> {
42        renew_token(&self.client.internal).await
43    }
44
45    #[allow(missing_docs)]
46    #[cfg(feature = "secrets")]
47    pub async fn login_access_token(
48        &self,
49        input: &AccessTokenLoginRequest,
50    ) -> Result<AccessTokenLoginResponse, LoginError> {
51        login_access_token(&self.client, input).await
52    }
53}
54
55#[cfg(feature = "internal")]
56impl AuthClient {
57    #[allow(missing_docs)]
58    pub fn password_strength(
59        &self,
60        password: String,
61        email: String,
62        additional_inputs: Vec<String>,
63    ) -> u8 {
64        password_strength(password, email, additional_inputs)
65    }
66
67    #[allow(missing_docs)]
68    pub fn satisfies_policy(
69        &self,
70        password: String,
71        strength: u8,
72        policy: &MasterPasswordPolicyOptions,
73    ) -> bool {
74        satisfies_policy(password, strength, policy)
75    }
76
77    #[allow(missing_docs)]
78    pub fn make_register_keys(
79        &self,
80        email: String,
81        password: String,
82        kdf: Kdf,
83    ) -> Result<RegisterKeyResponse, CryptoError> {
84        make_register_keys(email, password, kdf)
85    }
86
87    #[allow(missing_docs)]
88    pub fn make_register_tde_keys(
89        &self,
90        email: String,
91        org_public_key: String,
92        remember_device: bool,
93    ) -> Result<RegisterTdeKeyResponse, EncryptionSettingsError> {
94        make_register_tde_keys(&self.client, email, org_public_key, remember_device)
95    }
96
97    #[allow(missing_docs)]
98    pub fn make_key_connector_keys(&self) -> Result<KeyConnectorResponse, CryptoError> {
99        let mut rng = rand::thread_rng();
100        make_key_connector_keys(&mut rng)
101    }
102
103    #[allow(missing_docs)]
104    pub async fn prelogin(&self, email: String) -> Result<Kdf, PreloginError> {
105        use crate::auth::login::prelogin;
106
107        prelogin(&self.client, email).await
108    }
109
110    #[allow(missing_docs)]
111    pub async fn login_password(
112        &self,
113        input: &PasswordLoginRequest,
114    ) -> Result<PasswordLoginResponse, LoginError> {
115        login_password(&self.client, input).await
116    }
117
118    #[allow(missing_docs)]
119    pub async fn login_api_key(
120        &self,
121        input: &ApiKeyLoginRequest,
122    ) -> Result<ApiKeyLoginResponse, LoginError> {
123        login_api_key(&self.client, input).await
124    }
125
126    #[allow(missing_docs)]
127    pub async fn send_two_factor_email(
128        &self,
129        tf: &TwoFactorEmailRequest,
130    ) -> Result<(), TwoFactorEmailError> {
131        send_two_factor_email(&self.client, tf).await
132    }
133
134    #[allow(missing_docs)]
135    pub fn validate_password(
136        &self,
137        password: String,
138        password_hash: String,
139    ) -> Result<bool, AuthValidateError> {
140        validate_password(&self.client, password, password_hash)
141    }
142
143    #[allow(missing_docs)]
144    pub fn validate_password_user_key(
145        &self,
146        password: String,
147        encrypted_user_key: String,
148    ) -> Result<String, AuthValidateError> {
149        validate_password_user_key(&self.client, password, encrypted_user_key)
150    }
151
152    #[allow(missing_docs)]
153    pub fn validate_pin(
154        &self,
155        pin: String,
156        pin_protected_user_key: EncString,
157    ) -> Result<bool, AuthValidateError> {
158        validate_pin(&self.client, pin, pin_protected_user_key)
159    }
160
161    #[allow(missing_docs)]
162    pub fn new_auth_request(&self, email: &str) -> Result<AuthRequestResponse, CryptoError> {
163        new_auth_request(email)
164    }
165
166    #[allow(missing_docs)]
167    pub fn approve_auth_request(
168        &self,
169        public_key: String,
170    ) -> Result<UnsignedSharedKey, ApproveAuthRequestError> {
171        approve_auth_request(&self.client, public_key)
172    }
173
174    #[allow(missing_docs)]
175    pub fn trust_device(&self) -> Result<TrustDeviceResponse, TrustDeviceError> {
176        trust_device(&self.client)
177    }
178}
179
180#[cfg(feature = "internal")]
181impl AuthClient {
182    #[allow(missing_docs)]
183    pub async fn login_device(
184        &self,
185        email: String,
186        device_identifier: String,
187    ) -> Result<NewAuthRequestResponse, LoginError> {
188        use crate::auth::login::send_new_auth_request;
189
190        send_new_auth_request(&self.client, email, device_identifier).await
191    }
192
193    #[allow(missing_docs)]
194    pub async fn login_device_complete(
195        &self,
196        auth_req: NewAuthRequestResponse,
197    ) -> Result<(), LoginError> {
198        use crate::auth::login::complete_auth_request;
199
200        complete_auth_request(&self.client, auth_req).await
201    }
202}
203
204#[allow(missing_docs)]
205#[cfg(feature = "internal")]
206#[derive(Debug, thiserror::Error)]
207pub enum TrustDeviceError {
208    #[error(transparent)]
209    VaultLocked(#[from] crate::VaultLockedError),
210    #[error(transparent)]
211    Crypto(#[from] bitwarden_crypto::CryptoError),
212}
213
214#[cfg(feature = "internal")]
215fn trust_device(client: &Client) -> Result<TrustDeviceResponse, TrustDeviceError> {
216    use crate::key_management::SymmetricKeyId;
217
218    let key_store = client.internal.get_key_store();
219    let ctx = key_store.context();
220    // FIXME: [PM-18099] Once DeviceKey deals with KeyIds, this should be updated
221    #[allow(deprecated)]
222    let user_key = ctx.dangerous_get_symmetric_key(SymmetricKeyId::User)?;
223
224    Ok(DeviceKey::trust_device(user_key)?)
225}
226
227impl Client {
228    #[allow(missing_docs)]
229    pub fn auth(&self) -> AuthClient {
230        AuthClient {
231            client: self.clone(),
232        }
233    }
234}