Skip to content

Commit

Permalink
enforce the 2fa policy on login
Browse files Browse the repository at this point in the history
if a user doesn't have a second factor check if they are in an
organization that has the 2fa policy enabled to revoke their access
  • Loading branch information
stefan0xC committed Oct 21, 2023
1 parent bac4102 commit 91b1f48
Showing 1 changed file with 11 additions and 10 deletions.
21 changes: 11 additions & 10 deletions src/api/identity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ async fn _password_login(

let (mut device, new_device) = get_device(&data, conn, &user).await;

let twofactor_token = twofactor_auth(&user.uuid, &data, &mut device, ip, conn).await?;
let twofactor_token = twofactor_auth(&user, &data, &mut device, ip, conn).await?;

if CONFIG.mail_enabled() && new_device {
if let Err(e) = mail::send_new_device_logged_in(&user.email, &ip.ip.to_string(), &now, &device.name).await {
Expand Down Expand Up @@ -453,27 +453,28 @@ async fn get_device(data: &ConnectData, conn: &mut DbConn, user: &User) -> (Devi
}

async fn twofactor_auth(
user_uuid: &str,
user: &User,
data: &ConnectData,
device: &mut Device,
ip: &ClientIp,
conn: &mut DbConn,
) -> ApiResult<Option<String>> {
let twofactors = TwoFactor::find_by_user(user_uuid, conn).await;
let twofactors = TwoFactor::find_by_user(&user.uuid, conn).await;

// No twofactor token if twofactor is disabled
if twofactors.is_empty() {
_tf::enforce_2fa_policy(user, &user.uuid, device.atype, &ip.ip, conn).await?;
return Ok(None);
}

TwoFactorIncomplete::mark_incomplete(user_uuid, &device.uuid, &device.name, ip, conn).await?;
TwoFactorIncomplete::mark_incomplete(&user.uuid, &device.uuid, &device.name, ip, conn).await?;

let twofactor_ids: Vec<_> = twofactors.iter().map(|tf| tf.atype).collect();
let selected_id = data.two_factor_provider.unwrap_or(twofactor_ids[0]); // If we aren't given a two factor provider, assume the first one

let twofactor_code = match data.two_factor_token {
Some(ref code) => code,
None => err_json!(_json_err_twofactor(&twofactor_ids, user_uuid, conn).await?, "2FA token not provided"),
None => err_json!(_json_err_twofactor(&twofactor_ids, &user.uuid, conn).await?, "2FA token not provided"),
};

let selected_twofactor = twofactors.into_iter().find(|tf| tf.atype == selected_id && tf.enabled);
Expand All @@ -486,17 +487,17 @@ async fn twofactor_auth(

match TwoFactorType::from_i32(selected_id) {
Some(TwoFactorType::Authenticator) => {
_tf::authenticator::validate_totp_code_str(user_uuid, twofactor_code, &selected_data?, ip, conn).await?
_tf::authenticator::validate_totp_code_str(&user.uuid, twofactor_code, &selected_data?, ip, conn).await?
}
Some(TwoFactorType::Webauthn) => {
_tf::webauthn::validate_webauthn_login(user_uuid, twofactor_code, conn).await?
_tf::webauthn::validate_webauthn_login(&user.uuid, twofactor_code, conn).await?
}
Some(TwoFactorType::YubiKey) => _tf::yubikey::validate_yubikey_login(twofactor_code, &selected_data?).await?,
Some(TwoFactorType::Duo) => {
_tf::duo::validate_duo_login(data.username.as_ref().unwrap().trim(), twofactor_code, conn).await?
}
Some(TwoFactorType::Email) => {
_tf::email::validate_email_code_str(user_uuid, twofactor_code, &selected_data?, conn).await?
_tf::email::validate_email_code_str(&user.uuid, twofactor_code, &selected_data?, conn).await?
}

Some(TwoFactorType::Remember) => {
Expand All @@ -506,7 +507,7 @@ async fn twofactor_auth(
}
_ => {
err_json!(
_json_err_twofactor(&twofactor_ids, user_uuid, conn).await?,
_json_err_twofactor(&twofactor_ids, &user.uuid, conn).await?,
"2FA Remember token not provided"
)
}
Expand All @@ -520,7 +521,7 @@ async fn twofactor_auth(
),
}

TwoFactorIncomplete::mark_complete(user_uuid, &device.uuid, conn).await?;
TwoFactorIncomplete::mark_complete(&user.uuid, &device.uuid, conn).await?;

if !CONFIG.disable_2fa_remember() && remember == 1 {
Ok(Some(device.refresh_twofactor_remember()))
Expand Down

0 comments on commit 91b1f48

Please sign in to comment.