Skip to content

Commit

Permalink
enforce 2fa policy on login
Browse files Browse the repository at this point in the history
  • Loading branch information
stefan0xC committed Aug 28, 2023
1 parent f5dba0c commit 2ab7384
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 @@ -449,27 +449,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, asume 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 @@ -482,17 +483,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 @@ -502,7 +503,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 @@ -516,7 +517,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 2ab7384

Please sign in to comment.