From 0992a989d4eca6b7e5b563277f28ba8524a096ac Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9=20Bispo?= <abispo@bitwarden.com>
Date: Tue, 15 Nov 2022 14:17:26 +0000
Subject: [PATCH] [SG-778] Adjust mobile client to handle
 previously-responded-to passwordless request (#2190)

* [SG-778] Add properties to response model

* [SG-778] Add validation for request already answered

* [SG-778] Remove unnecessary properties

* [SG-778] Remove unnecessary assignments
---
 src/App/App.xaml.cs                                      | 2 +-
 .../Pages/Accounts/LoginPasswordlessRequestViewModel.cs  | 2 +-
 src/App/Pages/Accounts/LoginPasswordlessViewModel.cs     | 8 ++++++++
 src/App/Resources/AppResources.Designer.cs               | 9 +++++++++
 src/App/Resources/AppResources.resx                      | 3 +++
 src/Core/Models/Response/PasswordlessLoginResponse.cs    | 3 ++-
 6 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/src/App/App.xaml.cs b/src/App/App.xaml.cs
index bc9023a30..33dc82ed1 100644
--- a/src/App/App.xaml.cs
+++ b/src/App/App.xaml.cs
@@ -205,7 +205,7 @@ namespace Bit.App
                 FingerprintPhrase = loginRequestData.RequestFingerprint,
                 RequestDate = loginRequestData.CreationDate,
                 DeviceType = loginRequestData.RequestDeviceType,
-                Origin = loginRequestData.Origin,
+                Origin = loginRequestData.Origin
             });
             await _stateService.SetPasswordlessLoginNotificationAsync(null);
             _pushNotificationService.DismissLocalNotification(Constants.PasswordlessNotificationId);
diff --git a/src/App/Pages/Accounts/LoginPasswordlessRequestViewModel.cs b/src/App/Pages/Accounts/LoginPasswordlessRequestViewModel.cs
index b21437c7a..df8fce7dd 100644
--- a/src/App/Pages/Accounts/LoginPasswordlessRequestViewModel.cs
+++ b/src/App/Pages/Accounts/LoginPasswordlessRequestViewModel.cs
@@ -128,7 +128,7 @@ namespace Bit.App.Pages
             {
                 var response = await _authService.GetPasswordlessLoginResponseAsync(_requestId, _requestAccessCode);
 
-                if (!response.RequestApproved)
+                if (response.RequestApproved == null || !response.RequestApproved.Value)
                 {
                     return;
                 }
diff --git a/src/App/Pages/Accounts/LoginPasswordlessViewModel.cs b/src/App/Pages/Accounts/LoginPasswordlessViewModel.cs
index 1ca09b540..11c3400b5 100644
--- a/src/App/Pages/Accounts/LoginPasswordlessViewModel.cs
+++ b/src/App/Pages/Accounts/LoginPasswordlessViewModel.cs
@@ -117,6 +117,14 @@ namespace Bit.App.Pages
                 return;
             }
 
+            var loginRequestData = await _authService.GetPasswordlessLoginRequestByIdAsync(LoginRequest.Id);
+            if (loginRequestData.RequestApproved.HasValue && loginRequestData.ResponseDate.HasValue)
+            {
+                await _platformUtilsService.ShowDialogAsync(AppResources.ThisRequestIsNoLongerValid);
+                await Page.Navigation.PopModalAsync();
+                return;
+            }
+
             await _deviceActionService.ShowLoadingAsync(AppResources.Loading);
             await _authService.PasswordlessLoginAsync(LoginRequest.Id, LoginRequest.PubKey, approveRequest);
             await _deviceActionService.HideLoadingAsync();
diff --git a/src/App/Resources/AppResources.Designer.cs b/src/App/Resources/AppResources.Designer.cs
index 7da43e892..ff83de8a7 100644
--- a/src/App/Resources/AppResources.Designer.cs
+++ b/src/App/Resources/AppResources.Designer.cs
@@ -5876,6 +5876,15 @@ namespace Bit.App.Resources {
             }
         }
         
+        /// <summary>
+        ///   Looks up a localized string similar to This request is no longer valid.
+        /// </summary>
+        public static string ThisRequestIsNoLongerValid {
+            get {
+                return ResourceManager.GetString("ThisRequestIsNoLongerValid", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   Looks up a localized string similar to 3 days.
         /// </summary>
diff --git a/src/App/Resources/AppResources.resx b/src/App/Resources/AppResources.resx
index 2db7fa745..3a651bb62 100644
--- a/src/App/Resources/AppResources.resx
+++ b/src/App/Resources/AppResources.resx
@@ -2509,4 +2509,7 @@ Do you want to switch to this account?</value>
   <data name="ViewAllLoginOptions" xml:space="preserve">
     <value>View all log in options</value>
   </data>
+  <data name="ThisRequestIsNoLongerValid" xml:space="preserve">
+    <value>This request is no longer valid</value>
+  </data>
 </root>
diff --git a/src/Core/Models/Response/PasswordlessLoginResponse.cs b/src/Core/Models/Response/PasswordlessLoginResponse.cs
index ca830e75f..815036768 100644
--- a/src/Core/Models/Response/PasswordlessLoginResponse.cs
+++ b/src/Core/Models/Response/PasswordlessLoginResponse.cs
@@ -13,7 +13,8 @@ namespace Bit.Core.Models.Response
         public string Key { get; set; }
         public string MasterPasswordHash { get; set; }
         public DateTime CreationDate { get; set; }
-        public bool RequestApproved { get; set; }
+        public DateTime? ResponseDate { get; set; }
+        public bool? RequestApproved { get; set; }
         public string Origin { get; set; }
         public string RequestAccessCode { get; set; }
         public Tuple<byte[], byte[]> RequestKeyPair { get; set; }