Skip to content

Commit

Permalink
Allow Org Master-Pw policy enforcement (#4899)
Browse files Browse the repository at this point in the history
* Allow Org Master-Pw policy enforcement

We didn't returned the master password policy for the user.
If the `Require existing members to change their passwords` check was enabled this should trigger the login to show a change password dialog.

All the master password policies are merged into one during the login response and it will contain the max values and all `true` values which are set by all the different orgs if a user is an accepted member.

Fixes #4507

Signed-off-by: BlackDex <black.dex@gmail.com>

* Use .reduce instead of .fold

Signed-off-by: BlackDex <black.dex@gmail.com>

---------

Signed-off-by: BlackDex <black.dex@gmail.com>
  • Loading branch information
BlackDex authored Aug 27, 2024
1 parent 92f1530 commit 978f009
Showing 1 changed file with 43 additions and 3 deletions.
46 changes: 43 additions & 3 deletions src/api/identity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,18 @@ async fn _refresh_login(data: ConnectData, conn: &mut DbConn) -> JsonResult {
Ok(Json(result))
}

#[derive(Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
struct MasterPasswordPolicy {
min_complexity: u8,
min_length: u32,
require_lower: bool,
require_upper: bool,
require_numbers: bool,
require_special: bool,
enforce_on_login: bool,
}

async fn _password_login(
data: ConnectData,
user_uuid: &mut Option<String>,
Expand Down Expand Up @@ -282,6 +294,36 @@ async fn _password_login(
let (access_token, expires_in) = device.refresh_tokens(&user, scope_vec);
device.save(conn).await?;

// Fetch all valid Master Password Policies and merge them into one with all true's and larges numbers as one policy
let master_password_policies: Vec<MasterPasswordPolicy> =
OrgPolicy::find_accepted_and_confirmed_by_user_and_active_policy(
&user.uuid,
OrgPolicyType::MasterPassword,
conn,
)
.await
.into_iter()
.filter_map(|p| serde_json::from_str(&p.data).ok())
.collect();

let master_password_policy = if !master_password_policies.is_empty() {
let mut mpp_json = json!(master_password_policies.into_iter().reduce(|acc, policy| {
MasterPasswordPolicy {
min_complexity: acc.min_complexity.max(policy.min_complexity),
min_length: acc.min_length.max(policy.min_length),
require_lower: acc.require_lower || policy.require_lower,
require_upper: acc.require_upper || policy.require_upper,
require_numbers: acc.require_numbers || policy.require_numbers,
require_special: acc.require_special || policy.require_special,
enforce_on_login: acc.enforce_on_login || policy.enforce_on_login,
}
}));
mpp_json["object"] = json!("masterPasswordPolicy");
mpp_json
} else {
json!({"object": "masterPasswordPolicy"})
};

let mut result = json!({
"access_token": access_token,
"expires_in": expires_in,
Expand All @@ -297,9 +339,7 @@ async fn _password_login(
"KdfParallelism": user.client_kdf_parallelism,
"ResetMasterPassword": false, // TODO: Same as above
"ForcePasswordReset": false,
"MasterPasswordPolicy": {
"object": "masterPasswordPolicy",
},
"MasterPasswordPolicy": master_password_policy,

"scope": scope,
"unofficialServer": true,
Expand Down

0 comments on commit 978f009

Please sign in to comment.