From 37c14c3c69b244ec50f5c62b4c9260171607c1d8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20Garc=C3=ADa?=
 <dani-garcia@users.noreply.github.com>
Date: Mon, 11 Nov 2024 20:13:02 +0100
Subject: [PATCH] More authrequest fixes (#5176)

---
 src/api/core/accounts.rs | 23 ++++++++-------
 src/api/identity.rs      | 60 +++++++++++++++++++++++-----------------
 2 files changed, 47 insertions(+), 36 deletions(-)

diff --git a/src/api/core/accounts.rs b/src/api/core/accounts.rs
index e715d8bd..e6654add 100644
--- a/src/api/core/accounts.rs
+++ b/src/api/core/accounts.rs
@@ -1136,15 +1136,15 @@ async fn post_auth_request(
 
 #[get("/auth-requests/<uuid>")]
 async fn get_auth_request(uuid: &str, headers: Headers, mut conn: DbConn) -> JsonResult {
-    if headers.user.uuid != uuid {
-        err!("AuthRequest doesn't exist", "User uuid's do not match")
-    }
-
     let auth_request = match AuthRequest::find_by_uuid(uuid, &mut conn).await {
         Some(auth_request) => auth_request,
         None => err!("AuthRequest doesn't exist", "Record not found"),
     };
 
+    if headers.user.uuid != auth_request.user_uuid {
+        err!("AuthRequest doesn't exist", "User uuid's do not match")
+    }
+
     let response_date_utc = auth_request.response_date.map(|response_date| format_date(&response_date));
 
     Ok(Json(json!({
@@ -1190,15 +1190,18 @@ async fn put_auth_request(
         err!("AuthRequest doesn't exist", "User uuid's do not match")
     }
 
-    auth_request.approved = Some(data.request_approved);
-    auth_request.enc_key = Some(data.key);
-    auth_request.master_password_hash = data.master_password_hash;
-    auth_request.response_device_id = Some(data.device_identifier.clone());
-    auth_request.save(&mut conn).await?;
+    if data.request_approved {
+        auth_request.approved = Some(data.request_approved);
+        auth_request.enc_key = Some(data.key);
+        auth_request.master_password_hash = data.master_password_hash;
+        auth_request.response_device_id = Some(data.device_identifier.clone());
+        auth_request.save(&mut conn).await?;
 
-    if auth_request.approved.unwrap_or(false) {
         ant.send_auth_response(&auth_request.user_uuid, &auth_request.uuid).await;
         nt.send_auth_response(&auth_request.user_uuid, &auth_request.uuid, data.device_identifier, &mut conn).await;
+    } else {
+        // If denied, there's no reason to keep the request
+        auth_request.delete(&mut conn).await?;
     }
 
     let response_date_utc = auth_request.response_date.map(|response_date| format_date(&response_date));
diff --git a/src/api/identity.rs b/src/api/identity.rs
index 672f128c..003e4d97 100644
--- a/src/api/identity.rs
+++ b/src/api/identity.rs
@@ -165,20 +165,22 @@ async fn _password_login(
     // Set the user_uuid here to be passed back used for event logging.
     *user_uuid = Some(user.uuid.clone());
 
-    // Check password
-    let password = data.password.as_ref().unwrap();
-    if let Some(auth_request_uuid) = data.auth_request.clone() {
-        if let Some(auth_request) = AuthRequest::find_by_uuid(auth_request_uuid.as_str(), conn).await {
-            if !auth_request.check_access_code(password) {
-                err!(
-                    "Username or access code is incorrect. Try again",
-                    format!("IP: {}. Username: {}.", ip.ip, username),
-                    ErrorEvent {
-                        event: EventType::UserFailedLogIn,
-                    }
-                )
+    // Check if the user is disabled
+    if !user.enabled {
+        err!(
+            "This user has been disabled",
+            format!("IP: {}. Username: {}.", ip.ip, username),
+            ErrorEvent {
+                event: EventType::UserFailedLogIn
             }
-        } else {
+        )
+    }
+
+    let password = data.password.as_ref().unwrap();
+
+    // If we get an auth request, we don't check the user's password, but the access code of the auth request
+    if let Some(ref auth_request_uuid) = data.auth_request {
+        let Some(auth_request) = AuthRequest::find_by_uuid(auth_request_uuid.as_str(), conn).await else {
             err!(
                 "Auth request not found. Try again.",
                 format!("IP: {}. Username: {}.", ip.ip, username),
@@ -186,6 +188,23 @@ async fn _password_login(
                     event: EventType::UserFailedLogIn,
                 }
             )
+        };
+
+        // Delete the request after we used it
+        auth_request.delete(conn).await?;
+
+        if auth_request.user_uuid != user.uuid
+            || !auth_request.approved.unwrap_or(false)
+            || ip.ip.to_string() != auth_request.request_ip
+            || !auth_request.check_access_code(password)
+        {
+            err!(
+                "Username or access code is incorrect. Try again",
+                format!("IP: {}. Username: {}.", ip.ip, username),
+                ErrorEvent {
+                    event: EventType::UserFailedLogIn,
+                }
+            )
         }
     } else if !user.check_valid_password(password) {
         err!(
@@ -197,8 +216,8 @@ async fn _password_login(
         )
     }
 
-    // Change the KDF Iterations
-    if user.password_iterations != CONFIG.password_iterations() {
+    // Change the KDF Iterations (only when not logging in with an auth request)
+    if data.auth_request.is_none() && user.password_iterations != CONFIG.password_iterations() {
         user.password_iterations = CONFIG.password_iterations();
         user.set_password(password, None, false, None);
 
@@ -207,17 +226,6 @@ async fn _password_login(
         }
     }
 
-    // Check if the user is disabled
-    if !user.enabled {
-        err!(
-            "This user has been disabled",
-            format!("IP: {}. Username: {}.", ip.ip, username),
-            ErrorEvent {
-                event: EventType::UserFailedLogIn
-            }
-        )
-    }
-
     let now = Utc::now().naive_utc();
 
     if user.verified_at.is_none() && CONFIG.mail_enabled() && CONFIG.signups_verify() {
-- 
GitLab