bitwarden_uniffi/auth/
mod.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
use std::sync::Arc;

use bitwarden::{
    auth::{
        password::MasterPasswordPolicyOptions, AuthRequestResponse, KeyConnectorResponse,
        RegisterKeyResponse, RegisterTdeKeyResponse,
    },
    Error,
};
use bitwarden_crypto::{AsymmetricEncString, EncString, HashPurpose, Kdf, TrustDeviceResponse};

use crate::{error::Result, Client};

#[derive(uniffi::Object)]
pub struct ClientAuth(pub(crate) Arc<Client>);

#[uniffi::export(async_runtime = "tokio")]
impl ClientAuth {
    /// **API Draft:** Calculate Password Strength
    pub fn password_strength(
        &self,
        password: String,
        email: String,
        additional_inputs: Vec<String>,
    ) -> u8 {
        self.0
             .0
            .auth()
            .password_strength(password, email, additional_inputs)
    }

    /// Evaluate if the provided password satisfies the provided policy
    pub fn satisfies_policy(
        &self,
        password: String,
        strength: u8,
        policy: MasterPasswordPolicyOptions,
    ) -> bool {
        self.0
             .0
            .auth()
            .satisfies_policy(password, strength, &policy)
    }

    /// Hash the user password
    pub async fn hash_password(
        &self,
        email: String,
        password: String,
        kdf_params: Kdf,
        purpose: HashPurpose,
    ) -> Result<String> {
        Ok(self
            .0
             .0
            .kdf()
            .hash_password(email, password, kdf_params, purpose)
            .await?)
    }

    /// Generate keys needed for registration process
    pub fn make_register_keys(
        &self,
        email: String,
        password: String,
        kdf: Kdf,
    ) -> Result<RegisterKeyResponse> {
        Ok(self.0 .0.auth().make_register_keys(email, password, kdf)?)
    }

    /// Generate keys needed for TDE process
    pub fn make_register_tde_keys(
        &self,
        email: String,
        org_public_key: String,
        remember_device: bool,
    ) -> Result<RegisterTdeKeyResponse> {
        Ok(self
            .0
             .0
            .auth()
            .make_register_tde_keys(email, org_public_key, remember_device)?)
    }

    /// Generate keys needed to onboard a new user without master key to key connector
    pub fn make_key_connector_keys(&self) -> Result<KeyConnectorResponse> {
        Ok(self
            .0
             .0
            .auth()
            .make_key_connector_keys()
            .map_err(Error::Crypto)?)
    }

    /// Validate the user password
    ///
    /// To retrieve the user's password hash, use [`ClientAuth::hash_password`] with
    /// `HashPurpose::LocalAuthentication` during login and persist it. If the login method has no
    /// password, use the email OTP.
    pub fn validate_password(&self, password: String, password_hash: String) -> Result<bool> {
        Ok(self
            .0
             .0
            .auth()
            .validate_password(password, password_hash)?)
    }

    /// Validate the user password without knowing the password hash
    ///
    /// Used for accounts that we know have master passwords but that have not logged in with a
    /// password. Some example are login with device or TDE.
    ///
    /// This works by comparing the provided password against the encrypted user key.
    pub fn validate_password_user_key(
        &self,
        password: String,
        encrypted_user_key: String,
    ) -> Result<String> {
        Ok(self
            .0
             .0
            .auth()
            .validate_password_user_key(password, encrypted_user_key)?)
    }

    /// Validate the user PIN
    ///
    /// To validate the user PIN, you need to have the user's pin_protected_user_key. This key is
    /// obtained when enabling PIN unlock on the account with the `derive_pin_key` method.
    ///
    /// This works by comparing the decrypted user key with the current user key, so the client must
    /// be unlocked.
    pub fn validate_pin(&self, pin: String, pin_protected_user_key: EncString) -> Result<bool> {
        Ok(self.0 .0.auth().validate_pin(pin, pin_protected_user_key)?)
    }

    /// Initialize a new auth request
    pub fn new_auth_request(&self, email: String) -> Result<AuthRequestResponse> {
        Ok(self.0 .0.auth().new_auth_request(&email)?)
    }

    /// Approve an auth request
    pub fn approve_auth_request(&self, public_key: String) -> Result<AsymmetricEncString> {
        Ok(self.0 .0.auth().approve_auth_request(public_key)?)
    }

    /// Trust the current device
    pub fn trust_device(&self) -> Result<TrustDeviceResponse> {
        Ok(self.0 .0.auth().trust_device()?)
    }
}