mirror of
https://github.com/dani-garcia/vaultwarden.wiki.git
synced 2026-09-17 14:16:21 +03:00
fix(security): revoke 2FA remember tokens when credentials or 2FA change (#7682)
This commit is contained in:
@@ -16,8 +16,8 @@ use crate::{
|
|||||||
db::{
|
db::{
|
||||||
DbConn, DbPool,
|
DbConn, DbPool,
|
||||||
models::{
|
models::{
|
||||||
DeviceType, EventType, Membership, MembershipType, OrgPolicyType, Organization, OrganizationId, TwoFactor,
|
Device, DeviceType, EventType, Membership, MembershipType, OrgPolicyType, Organization, OrganizationId,
|
||||||
TwoFactorIncomplete, TwoFactorType, User, UserId,
|
TwoFactor, TwoFactorIncomplete, TwoFactorType, User, UserId,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mail,
|
mail,
|
||||||
@@ -151,6 +151,7 @@ async fn disable_twofactor(data: Json<DisableTwoFactorData>, headers: Headers, c
|
|||||||
|
|
||||||
if let Some(twofactor) = TwoFactor::find_by_user_and_type(&user.uuid, type_, &conn).await {
|
if let Some(twofactor) = TwoFactor::find_by_user_and_type(&user.uuid, type_, &conn).await {
|
||||||
twofactor.delete(&conn).await?;
|
twofactor.delete(&conn).await?;
|
||||||
|
Device::clear_twofactor_remember_by_user(&user.uuid, &conn).await?;
|
||||||
log_user_event(EventType::UserDisabled2fa as i32, &user.uuid, headers.device.atype, &headers.ip.ip, &conn)
|
log_user_event(EventType::UserDisabled2fa as i32, &user.uuid, headers.device.atype, &headers.ip.ip, &conn)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -905,6 +905,12 @@ async fn twofactor_auth(
|
|||||||
|
|
||||||
// Remove all twofactors from the user
|
// Remove all twofactors from the user
|
||||||
TwoFactor::delete_all_by_user(&user.uuid, conn).await?;
|
TwoFactor::delete_all_by_user(&user.uuid, conn).await?;
|
||||||
|
|
||||||
|
// No device may keep skipping 2FA once every second factor is gone.
|
||||||
|
// `device` is cleared in memory too, since saving it later would restore its token.
|
||||||
|
Device::clear_twofactor_remember_by_user(&user.uuid, conn).await?;
|
||||||
|
device.delete_twofactor_remember();
|
||||||
|
|
||||||
enforce_2fa_policy(user, &user.uuid, device.atype, &ip.ip, conn).await?;
|
enforce_2fa_policy(user, &user.uuid, device.atype, &ip.ip, conn).await?;
|
||||||
|
|
||||||
log_user_event(EventType::UserRecovered2fa as i32, &user.uuid, device.atype, &ip.ip, conn).await;
|
log_user_event(EventType::UserRecovered2fa as i32, &user.uuid, device.atype, &ip.ip, conn).await;
|
||||||
|
|||||||
@@ -266,10 +266,22 @@ impl Device {
|
|||||||
let devices = Self::find_by_user(user_uuid, conn).await;
|
let devices = Self::find_by_user(user_uuid, conn).await;
|
||||||
for mut device in devices {
|
for mut device in devices {
|
||||||
device.refresh_token = Device::generate_refresh_token();
|
device.refresh_token = Device::generate_refresh_token();
|
||||||
|
device.twofactor_remember = None;
|
||||||
device.save(false, conn).await?;
|
device.save(false, conn).await?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn clear_twofactor_remember_by_user(user_uuid: &UserId, conn: &DbConn) -> EmptyResult {
|
||||||
|
conn.run(move |conn| {
|
||||||
|
diesel::update(devices::table)
|
||||||
|
.filter(devices::user_uuid.eq(user_uuid))
|
||||||
|
.set(devices::twofactor_remember.eq::<Option<String>>(None))
|
||||||
|
.execute(conn)
|
||||||
|
.map_res("Error removing two factor remember tokens")
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Display)]
|
#[derive(Display)]
|
||||||
|
|||||||
Reference in New Issue
Block a user