Selaa lähdekoodia

Fix 2fa recovery endpoint (#6240)

The newer web-vaults handle the 2fa recovery code differently.
This commit fixes this by adding this new flow.

Fixes #6200
Fixes #6203

Signed-off-by: BlackDex <[email protected]>
Mathijs van Veluw 1 kuukausi sitten
vanhempi
sitoutus
7cc4dfabbf
2 muutettua tiedostoa jossa 20 lisäystä ja 4 poistoa
  1. 19 4
      src/api/identity.rs
  2. 1 0
      src/db/models/two_factor.rs

+ 19 - 4
src/api/identity.rs

@@ -267,7 +267,7 @@ async fn _sso_login(
         }
         Some((mut user, sso_user)) => {
             let mut device = get_device(&data, conn, &user).await?;
-            let twofactor_token = twofactor_auth(&user, &data, &mut device, ip, client_version, conn).await?;
+            let twofactor_token = twofactor_auth(&mut user, &data, &mut device, ip, client_version, conn).await?;
 
             if user.private_key.is_none() {
                 // User was invited a stub was created
@@ -431,7 +431,7 @@ async fn _password_login(
 
     let mut device = get_device(&data, conn, &user).await?;
 
-    let twofactor_token = twofactor_auth(&user, &data, &mut device, ip, client_version, conn).await?;
+    let twofactor_token = twofactor_auth(&mut user, &data, &mut device, ip, client_version, conn).await?;
 
     let auth_tokens = auth::AuthTokens::new(&device, &user, AuthMethod::Password, data.client_id);
 
@@ -658,7 +658,7 @@ async fn get_device(data: &ConnectData, conn: &mut DbConn, user: &User) -> ApiRe
 }
 
 async fn twofactor_auth(
-    user: &User,
+    user: &mut User,
     data: &ConnectData,
     device: &mut Device,
     ip: &ClientIp,
@@ -723,7 +723,6 @@ async fn twofactor_auth(
         Some(TwoFactorType::Email) => {
             email::validate_email_code_str(&user.uuid, twofactor_code, &selected_data?, &ip.ip, conn).await?
         }
-
         Some(TwoFactorType::Remember) => {
             match device.twofactor_remember {
                 Some(ref code) if !CONFIG.disable_2fa_remember() && ct_eq(code, twofactor_code) => {
@@ -737,6 +736,22 @@ async fn twofactor_auth(
                 }
             }
         }
+        Some(TwoFactorType::RecoveryCode) => {
+            // Check if recovery code is correct
+            if !user.check_valid_recovery_code(twofactor_code) {
+                err!("Recovery code is incorrect. Try again.")
+            }
+
+            // Remove all twofactors from the user
+            TwoFactor::delete_all_by_user(&user.uuid, 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;
+
+            // Remove the recovery code, not needed without twofactors
+            user.totp_recover = None;
+            user.save(conn).await?;
+        }
         _ => err!(
             "Invalid two factor provider",
             ErrorEvent {

+ 1 - 0
src/db/models/two_factor.rs

@@ -31,6 +31,7 @@ pub enum TwoFactorType {
     Remember = 5,
     OrganizationDuo = 6,
     Webauthn = 7,
+    RecoveryCode = 8,
 
     // These are implementation details
     U2fRegisterChallenge = 1000,