bitwarden_core/auth/
auth_client.rs

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