From 4eb608ec112bb74c5cc1a372ecc34267d39d76f6 Mon Sep 17 00:00:00 2001 From: Federico Maccaroni Date: Wed, 17 Apr 2024 09:05:46 -0300 Subject: [PATCH] PM-7385 Fix IFido2MakeCredentialConfirmationUserInterface resolve and usage to be constrained to Android. (#3164) --- src/Core/App.xaml.cs | 12 ++++++++---- src/Core/Pages/Vault/CipherAddEditPage.xaml.cs | 4 ++++ src/Core/Pages/Vault/CipherAddEditPageViewModel.cs | 7 +++++-- src/Core/Pages/Vault/CiphersPageViewModel.cs | 4 ++++ .../Utilities/AccountManagement/AccountsManager.cs | 8 ++++++-- src/Core/Utilities/AppHelpers.cs | 12 ++++++++---- 6 files changed, 35 insertions(+), 12 deletions(-) diff --git a/src/Core/App.xaml.cs b/src/Core/App.xaml.cs index fa9b448f9..3a33fd31c 100644 --- a/src/Core/App.xaml.cs +++ b/src/Core/App.xaml.cs @@ -38,7 +38,9 @@ namespace Bit.App private readonly IPushNotificationService _pushNotificationService; private readonly IConfigService _configService; private readonly ILogger _logger; - private LazyResolve _userVerificationMediatorService = new LazyResolve(); +#if ANDROID + private LazyResolve _fido2MakeCredentialConfirmationUserInterface = new LazyResolve(); +#endif private static bool _isResumed; // these variables are static because the app is launching new activities on notification click, creating new instances of App. @@ -332,10 +334,12 @@ namespace Bit.App || message.Command == "unlocked" || message.Command == AccountsManagerMessageCommands.ACCOUNT_SWITCH_COMPLETED) { - if (message.Command == AccountsManagerMessageCommands.ACCOUNT_SWITCH_COMPLETED && _userVerificationMediatorService.Value.IsConfirmingNewCredential) +#if ANDROID + if (message.Command == AccountsManagerMessageCommands.ACCOUNT_SWITCH_COMPLETED && _fido2MakeCredentialConfirmationUserInterface.Value.IsConfirmingNewCredential) { - _userVerificationMediatorService.Value.OnConfirmationException(new AccountSwitchedException()); + _fido2MakeCredentialConfirmationUserInterface.Value.OnConfirmationException(new AccountSwitchedException()); } +#endif lock (_processingLoginRequestLock) { @@ -720,7 +724,7 @@ namespace Bit.App // If we are in background we add the Navigation Actions to a queue to execute when the app resumes. // Links: https://github.com/dotnet/maui/issues/11501 and https://bitwarden.atlassian.net/wiki/spaces/NMME/pages/664862722/MainPage+Assignments+not+working+on+Android+on+Background+or+App+resume #if ANDROID - if (_userVerificationMediatorService != null && _userVerificationMediatorService.Value.IsConfirmingNewCredential) + if (_fido2MakeCredentialConfirmationUserInterface != null && _fido2MakeCredentialConfirmationUserInterface.Value.IsConfirmingNewCredential) { // if it's creating passkey // and we have an active pending TaskCompletionSource diff --git a/src/Core/Pages/Vault/CipherAddEditPage.xaml.cs b/src/Core/Pages/Vault/CipherAddEditPage.xaml.cs index 4a9744d9b..2d16e8656 100644 --- a/src/Core/Pages/Vault/CipherAddEditPage.xaml.cs +++ b/src/Core/Pages/Vault/CipherAddEditPage.xaml.cs @@ -19,7 +19,9 @@ namespace Bit.App.Pages private readonly IAutofillHandler _autofillHandler; private readonly IVaultTimeoutService _vaultTimeoutService; private readonly IUserVerificationService _userVerificationService; +#if ANDROID private readonly LazyResolve _fido2MakeCredentialConfirmationUserInterface = new LazyResolve(); +#endif private CipherAddEditPageViewModel _vm; private bool _fromAutofill; @@ -46,7 +48,9 @@ namespace Bit.App.Pages _appOptions = appOptions; _fromAutofill = fromAutofill; FromAutofillFramework = _appOptions?.FromAutofillFramework ?? false; +#if ANDROID FromAndroidFido2Framework = _fido2MakeCredentialConfirmationUserInterface.Value.IsConfirmingNewCredential; +#endif InitializeComponent(); _vm = BindingContext as CipherAddEditPageViewModel; _vm.Page = this; diff --git a/src/Core/Pages/Vault/CipherAddEditPageViewModel.cs b/src/Core/Pages/Vault/CipherAddEditPageViewModel.cs index 0797e6218..65a0c3979 100644 --- a/src/Core/Pages/Vault/CipherAddEditPageViewModel.cs +++ b/src/Core/Pages/Vault/CipherAddEditPageViewModel.cs @@ -96,7 +96,10 @@ namespace Bit.App.Pages _autofillHandler = ServiceContainer.Resolve(); _watchDeviceService = ServiceContainer.Resolve(); _accountsManager = ServiceContainer.Resolve(); - _fido2MakeCredentialConfirmationUserInterface = ServiceContainer.Resolve(); + if (ServiceContainer.TryResolve(out var fido2MakeService)) + { + _fido2MakeCredentialConfirmationUserInterface = fido2MakeService; + } _userVerificationMediatorService = ServiceContainer.Resolve(); GeneratePasswordCommand = new Command(GeneratePassword); @@ -332,7 +335,7 @@ namespace Bit.App.Pages public async Task LoadAsync(AppOptions appOptions = null) { _fromOtp = appOptions?.OtpData != null; - IsFromFido2Framework = _fido2MakeCredentialConfirmationUserInterface.IsConfirmingNewCredential; + IsFromFido2Framework = _fido2MakeCredentialConfirmationUserInterface?.IsConfirmingNewCredential == true; var myEmail = await _stateService.GetEmailAsync(); OwnershipOptions.Add(new KeyValuePair(myEmail, null)); diff --git a/src/Core/Pages/Vault/CiphersPageViewModel.cs b/src/Core/Pages/Vault/CiphersPageViewModel.cs index cfa13324b..3479f9ecf 100644 --- a/src/Core/Pages/Vault/CiphersPageViewModel.cs +++ b/src/Core/Pages/Vault/CiphersPageViewModel.cs @@ -22,7 +22,9 @@ namespace Bit.App.Pages private readonly IPasswordRepromptService _passwordRepromptService; private readonly IOrganizationService _organizationService; private readonly IPolicyService _policyService; +#if ANDROID private readonly LazyResolve _fido2MakeCredentialConfirmationUserInterface = new LazyResolve(); +#endif private CancellationTokenSource _searchCancellationTokenSource; private readonly ILogger _logger; @@ -175,11 +177,13 @@ namespace Bit.App.Pages public async Task SelectCipherAsync(CipherView cipher) { +#if ANDROID if (_fido2MakeCredentialConfirmationUserInterface.Value.IsConfirmingNewCredential) { await _fido2MakeCredentialConfirmationUserInterface.Value.ConfirmAsync(cipher.Id, cipher.Login.HasFido2Credentials, null); return; } +#endif string selection = null; diff --git a/src/Core/Utilities/AccountManagement/AccountsManager.cs b/src/Core/Utilities/AccountManagement/AccountsManager.cs index 5f1a9962e..6657c6478 100644 --- a/src/Core/Utilities/AccountManagement/AccountsManager.cs +++ b/src/Core/Utilities/AccountManagement/AccountsManager.cs @@ -20,7 +20,9 @@ namespace Bit.App.Utilities.AccountManagement private readonly IMessagingService _messagingService; private readonly IWatchDeviceService _watchDeviceService; private readonly IConditionedAwaiterManager _conditionedAwaiterManager; - private LazyResolve _userVerificationMediatorService = new LazyResolve(); +#if ANDROID + private LazyResolve _fido2MakeCredentialConfirmationUserInterface = new LazyResolve(); +#endif Func _getOptionsFunc; private IAccountsManagerHost _accountsManagerHost; @@ -101,12 +103,14 @@ namespace Bit.App.Utilities.AccountManagement { _accountsManagerHost.Navigate(NavigationTarget.AddEditCipher); } - else if (_userVerificationMediatorService.Value.IsConfirmingNewCredential) +#if ANDROID + else if (_fido2MakeCredentialConfirmationUserInterface.Value.IsConfirmingNewCredential) { // If we are already confirming a credential we don't need to navigate again. // This could happen when switching accounts for example. return; } +#endif else if (Options.FromFido2Framework) { var deviceActionService = Bit.Core.Utilities.ServiceContainer.Resolve(); diff --git a/src/Core/Utilities/AppHelpers.cs b/src/Core/Utilities/AppHelpers.cs index fe3f8f974..b248bd8dc 100644 --- a/src/Core/Utilities/AppHelpers.cs +++ b/src/Core/Utilities/AppHelpers.cs @@ -432,8 +432,10 @@ namespace Bit.App.Utilities // this is called after login in or unlocking so we can assume the vault has been unlocked in this transaction here. appOptions.HasUnlockedInThisTransaction = true; - var userVerificationMediatorService = ServiceContainer.Resolve(); - userVerificationMediatorService.SetCheckHasVaultBeenUnlockedInThisTransaction(() => appOptions?.HasUnlockedInThisTransaction == true); +#if ANDROID + var fido2MakeCredentialConfirmationUserInterface = ServiceContainer.Resolve(); + fido2MakeCredentialConfirmationUserInterface.SetCheckHasVaultBeenUnlockedInThisTransaction(() => appOptions?.HasUnlockedInThisTransaction == true); +#endif if (appOptions.FromAutofillFramework && appOptions.SaveType.HasValue) { @@ -441,13 +443,15 @@ namespace Bit.App.Utilities return true; } +#if ANDROID // If we are waiting for an unlock vault we don't want to trigger 'ExecuteFido2CredentialActionAsync' again, // as it's already running. We just need to 'ConfirmUnlockVault' on the 'userVerificationMediatorService'. - if (userVerificationMediatorService.IsWaitingUnlockVault) + if (fido2MakeCredentialConfirmationUserInterface.IsWaitingUnlockVault) { - userVerificationMediatorService.ConfirmVaultUnlocked(); + fido2MakeCredentialConfirmationUserInterface.ConfirmVaultUnlocked(); return true; } +#endif if (appOptions.FromFido2Framework && !string.IsNullOrWhiteSpace(appOptions.Fido2CredentialAction)) {