Skip to content

Commit

Permalink
Add support for setting password
Browse files Browse the repository at this point in the history
  • Loading branch information
Hinton committed Apr 12, 2024
1 parent b611974 commit b38f25e
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 5 deletions.
18 changes: 16 additions & 2 deletions crates/bitwarden-uniffi/src/auth/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use std::sync::Arc;

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

Expand Down Expand Up @@ -149,4 +149,18 @@ impl ClientAuth {
pub async fn trust_device(&self) -> Result<TrustDeviceResponse> {
Ok(self.0 .0.write().await.auth().trust_device()?)
}

/// Set a new password for the user.
///
/// Presumes that the user is logged in using a username, and has crypto initialized.
pub async fn set_password(&self, new_password: String) -> Result<SetPasswordResponse> {
Ok(self
.0
.0
.write()
.await
.auth()
.set_password(new_password)
.await?)
}

Check warning on line 165 in crates/bitwarden-uniffi/src/auth/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-uniffi/src/auth/mod.rs#L156-L165

Added lines #L156 - L165 were not covered by tests
}
5 changes: 5 additions & 0 deletions crates/bitwarden/src/auth/client_auth.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#[cfg(feature = "internal")]
use bitwarden_crypto::{AsymmetricEncString, DeviceKey, TrustDeviceResponse};

use super::password::{set_password, SetPasswordResponse};
#[cfg(feature = "mobile")]
use crate::auth::login::NewAuthRequestResponse;
#[cfg(feature = "secrets")]
Expand Down Expand Up @@ -134,6 +135,10 @@ impl<'a> ClientAuth<'a> {
pub fn trust_device(&self) -> Result<TrustDeviceResponse> {
trust_device(self.client)
}

pub async fn set_password(&self, password: String) -> Result<SetPasswordResponse> {
set_password(self.client, password).await
}

Check warning on line 141 in crates/bitwarden/src/auth/client_auth.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden/src/auth/client_auth.rs#L139-L141

Added lines #L139 - L141 were not covered by tests
}

#[cfg(feature = "mobile")]
Expand Down
6 changes: 6 additions & 0 deletions crates/bitwarden/src/auth/password/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,9 @@ pub(crate) use validate::validate_password;
pub(crate) use validate::validate_password_user_key;
mod strength;
pub(crate) use strength::password_strength;
#[cfg(feature = "internal")]
mod set;
#[cfg(feature = "internal")]
pub(crate) use set::set_password;
#[cfg(feature = "internal")]
pub use set::SetPasswordResponse;
43 changes: 43 additions & 0 deletions crates/bitwarden/src/auth/password/set.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use bitwarden_crypto::{EncString, HashPurpose, MasterKey};

use crate::{
client::{LoginMethod, UserLoginMethod},
error::{Error, Result},
Client,
};

#[cfg_attr(feature = "mobile", derive(uniffi::Record))]
pub struct SetPasswordResponse {
// Password hash for server authentication
password_hash: String,
// MasterKey (password) protected user key
protected_user_key: EncString,
}

pub(crate) async fn set_password(client: &Client, password: String) -> Result<SetPasswordResponse> {
let user_key = client
.get_encryption_settings()?
.get_key(&None)
.ok_or(Error::VaultLocked)?;

Check warning on line 21 in crates/bitwarden/src/auth/password/set.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden/src/auth/password/set.rs#L17-L21

Added lines #L17 - L21 were not covered by tests

let login_method = client
.get_login_method()
.as_ref()
.ok_or(Error::NotAuthenticated)?;

Check warning on line 26 in crates/bitwarden/src/auth/password/set.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden/src/auth/password/set.rs#L23-L26

Added lines #L23 - L26 were not covered by tests

let (email, kdf) = match login_method {

Check warning on line 28 in crates/bitwarden/src/auth/password/set.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden/src/auth/password/set.rs#L28

Added line #L28 was not covered by tests
LoginMethod::User(
UserLoginMethod::Username { email, kdf, .. }
| UserLoginMethod::ApiKey { email, kdf, .. },
) => (email, kdf),
_ => return Err(Error::NotAuthenticated),

Check warning on line 33 in crates/bitwarden/src/auth/password/set.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden/src/auth/password/set.rs#L30-L33

Added lines #L30 - L33 were not covered by tests
};

let master_key = MasterKey::derive(password.as_bytes(), email.as_bytes(), kdf)?;

Check warning on line 36 in crates/bitwarden/src/auth/password/set.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden/src/auth/password/set.rs#L36

Added line #L36 was not covered by tests

Ok(SetPasswordResponse {
password_hash: master_key
.derive_master_key_hash(password.as_bytes(), HashPurpose::ServerAuthorization)?,
protected_user_key: master_key.encrypt_user_key(user_key)?,

Check warning on line 41 in crates/bitwarden/src/auth/password/set.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden/src/auth/password/set.rs#L39-L41

Added lines #L39 - L41 were not covered by tests
})
}

Check warning on line 43 in crates/bitwarden/src/auth/password/set.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden/src/auth/password/set.rs#L43

Added line #L43 was not covered by tests
2 changes: 1 addition & 1 deletion crates/bitwarden/src/mobile/client_kdf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ impl<'a> ClientKdf<'a> {
kdf_params: Kdf,
purpose: HashPurpose,
) -> Result<String> {
hash_password(self.client, email, password, kdf_params, purpose).await
hash_password(self.client, email, password, &kdf_params, purpose).await
}
}

Expand Down
4 changes: 2 additions & 2 deletions crates/bitwarden/src/mobile/kdf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ pub async fn hash_password(
_client: &Client,
email: String,
password: String,
kdf_params: Kdf,
kdf_params: &Kdf,
purpose: HashPurpose,
) -> Result<String> {
let master_key = MasterKey::derive(password.as_bytes(), email.as_bytes(), &kdf_params)?;
let master_key = MasterKey::derive(password.as_bytes(), email.as_bytes(), kdf_params)?;

Ok(master_key.derive_master_key_hash(password.as_bytes(), purpose)?)
}

0 comments on commit b38f25e

Please sign in to comment.