Skip to main content

bitwarden_uniffi/auth/
mod.rs

1use bitwarden_core::auth::{
2    AuthRequestResponse, KeyConnectorResponse, RegisterKeyResponse, RegisterTdeKeyResponse,
3    password::MasterPasswordPolicyOptions,
4};
5use bitwarden_crypto::{
6    EncString, HashPurpose, Kdf, TrustDeviceResponse, UnsignedSharedKey,
7    safe::PasswordProtectedKeyEnvelope,
8};
9use bitwarden_encoding::B64;
10
11use crate::{auth::registration::RegistrationClient, error::Result};
12
13mod registration;
14
15#[derive(uniffi::Object)]
16pub struct AuthClient(pub(crate) bitwarden_core::Client);
17
18#[uniffi::export(async_runtime = "tokio")]
19impl AuthClient {
20    /// Client for initializing user account cryptography and unlock methods after JIT provisioning
21    pub fn registration(&self) -> RegistrationClient {
22        RegistrationClient(self.0.clone())
23    }
24
25    /// Calculate Password Strength
26    pub fn password_strength(
27        &self,
28        password: String,
29        email: String,
30        additional_inputs: Vec<String>,
31    ) -> u8 {
32        self.0
33            .auth()
34            .password_strength(password, email, additional_inputs)
35    }
36
37    /// Evaluate if the provided password satisfies the provided policy
38    pub fn satisfies_policy(
39        &self,
40        password: String,
41        strength: u8,
42        policy: MasterPasswordPolicyOptions,
43    ) -> bool {
44        self.0.auth().satisfies_policy(password, strength, &policy)
45    }
46
47    /// Hash the user password
48    pub async fn hash_password(
49        &self,
50        email: String,
51        password: String,
52        kdf_params: Kdf,
53        purpose: HashPurpose,
54    ) -> Result<B64> {
55        Ok(self
56            .0
57            .kdf()
58            .hash_password(email, password, kdf_params, purpose)
59            .await?)
60    }
61
62    /// Generate keys needed for registration process
63    pub fn make_register_keys(
64        &self,
65        email: String,
66        password: String,
67        kdf: Kdf,
68    ) -> Result<RegisterKeyResponse> {
69        Ok(self.0.auth().make_register_keys(email, password, kdf)?)
70    }
71
72    /// Generate keys needed for TDE process
73    pub async fn make_register_tde_keys(
74        &self,
75        email: String,
76        org_public_key: B64,
77        remember_device: bool,
78    ) -> Result<RegisterTdeKeyResponse> {
79        Ok(self
80            .0
81            .auth()
82            .make_register_tde_keys(email, org_public_key, remember_device)
83            .await?)
84    }
85
86    /// Generate keys needed to onboard a new user without master key to key connector
87    pub fn make_key_connector_keys(&self) -> Result<KeyConnectorResponse> {
88        Ok(self.0.auth().make_key_connector_keys()?)
89    }
90
91    /// Validate the user password
92    ///
93    /// To retrieve the user's password hash, use [`AuthClient::hash_password`] with
94    /// `HashPurpose::LocalAuthentication` during login and persist it. If the login method has no
95    /// password, use the email OTP.
96    pub async fn validate_password(&self, password: String, password_hash: B64) -> Result<bool> {
97        Ok(self
98            .0
99            .auth()
100            .validate_password(password, password_hash)
101            .await?)
102    }
103
104    /// Validate the user password without knowing the password hash
105    ///
106    /// Used for accounts that we know have master passwords but that have not logged in with a
107    /// password. Some example are login with device or TDE.
108    ///
109    /// This works by comparing the provided password against the encrypted user key.
110    pub async fn validate_password_user_key(
111        &self,
112        password: String,
113        encrypted_user_key: String,
114    ) -> Result<B64> {
115        Ok(self
116            .0
117            .auth()
118            .validate_password_user_key(password, encrypted_user_key)
119            .await?)
120    }
121
122    /// Validate the user PIN
123    ///
124    /// To validate the user PIN, you need to have the user's pin_protected_user_key. This key is
125    /// obtained when enabling PIN unlock on the account with the `derive_pin_key` method.
126    ///
127    /// This works by comparing the decrypted user key with the current user key, so the client must
128    /// be unlocked.
129    pub async fn validate_pin(
130        &self,
131        pin: String,
132        pin_protected_user_key: EncString,
133    ) -> Result<bool> {
134        Ok(self
135            .0
136            .auth()
137            .validate_pin(pin, pin_protected_user_key)
138            .await?)
139    }
140
141    /// Validates a PIN against a PIN-protected user key envelope.
142    ///
143    /// The `pin_protected_user_key_envelope` key is obtained when enabling PIN unlock on the
144    /// account with the [bitwarden_core::key_management::CryptoClient::enroll_pin] method.
145    ///
146    /// Returns `false` if validation fails for any reason:
147    /// - The PIN is incorrect
148    /// - The envelope is corrupted or malformed
149    pub fn validate_pin_protected_user_key_envelope(
150        &self,
151        pin: String,
152        pin_protected_user_key_envelope: PasswordProtectedKeyEnvelope,
153    ) -> bool {
154        self.0
155            .auth()
156            .validate_pin_protected_user_key_envelope(pin, pin_protected_user_key_envelope)
157    }
158
159    /// Initialize a new auth request
160    pub fn new_auth_request(&self, email: String) -> Result<AuthRequestResponse> {
161        Ok(self.0.auth().new_auth_request(&email)?)
162    }
163
164    /// Approve an auth request
165    pub fn approve_auth_request(&self, public_key: B64) -> Result<UnsignedSharedKey> {
166        Ok(self.0.auth().approve_auth_request(public_key)?)
167    }
168
169    /// Trust the current device
170    pub fn trust_device(&self) -> Result<TrustDeviceResponse> {
171        Ok(self.0.auth().trust_device()?)
172    }
173}