diff --git a/src/Core/Abstractions/IStateService.cs b/src/Core/Abstractions/IStateService.cs index 64ed18855..44ec8079f 100644 --- a/src/Core/Abstractions/IStateService.cs +++ b/src/Core/Abstractions/IStateService.cs @@ -186,6 +186,7 @@ namespace Bit.Core.Abstractions Task GetActiveUserRegionAsync(); Task GetPreAuthRegionAsync(); Task SetPreAuthRegionAsync(BwRegion value); + Task ReloadStateAsync(); [Obsolete("Use GetPinKeyEncryptedUserKeyAsync instead, left for migration purposes")] Task GetPinProtectedAsync(string userId = null); [Obsolete("Use SetPinKeyEncryptedUserKeyAsync instead, left for migration purposes")] diff --git a/src/Core/Services/StateService.cs b/src/Core/Services/StateService.cs index e8c997f18..a6685d391 100644 --- a/src/Core/Services/StateService.cs +++ b/src/Core/Services/StateService.cs @@ -1688,6 +1688,11 @@ namespace Bit.Core.Services await _storageService.SaveAsync(Constants.iOSExtensionActiveUserIdKey, userId); } + public async Task ReloadStateAsync() + { + _state = await GetStateFromStorageAsync() ?? new State(); + } + private async Task CheckStateAsync() { if (!_migrationChecked) @@ -1699,7 +1704,7 @@ namespace Bit.Core.Services if (_state == null) { - _state = await GetStateFromStorageAsync() ?? new State(); + await ReloadStateAsync(); } } diff --git a/src/iOS.Autofill/CredentialProviderViewController.Passkeys.cs b/src/iOS.Autofill/CredentialProviderViewController.Passkeys.cs index 46761267c..8e1486abb 100644 --- a/src/iOS.Autofill/CredentialProviderViewController.Passkeys.cs +++ b/src/iOS.Autofill/CredentialProviderViewController.Passkeys.cs @@ -66,6 +66,10 @@ namespace Bit.iOS.Autofill } } + catch (Fido2AuthenticatorException) + { + CancelRequest(ASExtensionErrorCode.Failed); + } catch (Exception ex) { OnProvidingCredentialException(ex); @@ -79,7 +83,7 @@ namespace Bit.iOS.Autofill return; } - InitAppIfNeeded(); + await InitAppIfNeededAsync(); if (!await IsAuthed()) { @@ -174,7 +178,7 @@ namespace Bit.iOS.Autofill private async Task ProvideCredentialWithoutUserInteractionAsync(ASPasskeyCredentialRequest passkeyCredentialRequest) { - InitAppIfNeeded(); + await InitAppIfNeededAsync(); await _stateService.Value.SetPasswordRepromptAutofillAsync(false); await _stateService.Value.SetPasswordVerifiedAutofillAsync(false); if (!await IsAuthed() || await IsLocked()) diff --git a/src/iOS.Autofill/CredentialProviderViewController.cs b/src/iOS.Autofill/CredentialProviderViewController.cs index 51b753769..2bcd37f5c 100644 --- a/src/iOS.Autofill/CredentialProviderViewController.cs +++ b/src/iOS.Autofill/CredentialProviderViewController.cs @@ -10,6 +10,7 @@ using Bit.Core.Abstractions; using Bit.Core.Enums; using Bit.Core.Services; using Bit.Core.Utilities; +using Bit.Core.Utilities.Fido2; using Bit.iOS.Autofill.Models; using Bit.iOS.Core.Utilities; using Bit.iOS.Core.Views; @@ -46,7 +47,7 @@ namespace Bit.iOS.Autofill { try { - InitAppIfNeeded(); + InitAppIfNeededAsync().FireAndForget(ex => OnProvidingCredentialException(ex)); base.ViewDidLoad(); @@ -77,7 +78,7 @@ namespace Bit.iOS.Autofill { try { - InitAppIfNeeded(); + await InitAppIfNeededAsync(); _context.ServiceIdentifiers = serviceIdentifiers; if (serviceIdentifiers.Length > 0) { @@ -209,7 +210,7 @@ namespace Bit.iOS.Autofill { try { - InitAppIfNeeded(); + await InitAppIfNeededAsync(); _context.Configuring = true; _context.VaultUnlockedDuringThisSession = false; @@ -228,7 +229,7 @@ namespace Bit.iOS.Autofill private async Task ProvideCredentialWithoutUserInteractionAsync(ASPasswordCredentialIdentity credentialIdentity) { - InitAppIfNeeded(); + await InitAppIfNeededAsync(); await _stateService.Value.SetPasswordRepromptAutofillAsync(false); await _stateService.Value.SetPasswordVerifiedAutofillAsync(false); if (!await IsAuthed() || await IsLocked()) @@ -244,7 +245,7 @@ namespace Bit.iOS.Autofill private async Task PrepareInterfaceToProvideCredentialAsync(Action updateContext) { - InitAppIfNeeded(); + await InitAppIfNeededAsync(); if (!await IsAuthed()) { await _accountsManager.NavigateOnAccountChangeAsync(false); @@ -476,7 +477,7 @@ namespace Bit.iOS.Autofill { if (!string.IsNullOrWhiteSpace(decCipher.Login.Totp) && - (cipher.OrganizationUseTotp || await _stateService.Value.CanAccessPremiumAsync())) + (cipher.OrganizationUseTotp || await _stateService.Value.CanAccessPremiumAsync())) { totpCode = await ServiceContainer.Resolve().GetCodeAsync(decCipher.Login.Totp); } @@ -484,6 +485,10 @@ namespace Bit.iOS.Autofill CompleteRequest(decCipher.Id, decCipher.Login.Username, decCipher.Login.Password, totpCode); } + catch (Fido2AuthenticatorException) + { + CancelRequest(ASExtensionErrorCode.Failed); + } catch (Exception ex) { OnProvidingCredentialException(ex); @@ -541,12 +546,14 @@ namespace Bit.iOS.Autofill _nfcSession, out _nfcDelegate, out _accountsManager); } - private void InitAppIfNeeded() + private async Task InitAppIfNeededAsync() { if (ServiceContainer.RegisteredServices == null || ServiceContainer.RegisteredServices.Count == 0) { - InitApp(); + await MainThread.InvokeOnMainThreadAsync(InitApp); } + + await _stateService.Value.ReloadStateAsync(); } private void LaunchHomePage()