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