2022-01-18 15:52:08 +01:00
|
|
|
|
using System;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using Bit.App.Abstractions;
|
2022-02-23 18:40:17 +01:00
|
|
|
|
using Bit.App.Controls;
|
2019-05-15 23:37:59 +02:00
|
|
|
|
using Bit.App.Resources;
|
2022-01-18 15:52:08 +01:00
|
|
|
|
using Bit.App.Utilities;
|
2019-05-15 23:37:59 +02:00
|
|
|
|
using Bit.Core;
|
|
|
|
|
using Bit.Core.Abstractions;
|
|
|
|
|
using Bit.Core.Enums;
|
|
|
|
|
using Bit.Core.Models.Domain;
|
2020-09-03 18:30:40 +02:00
|
|
|
|
using Bit.Core.Models.Request;
|
2022-01-18 15:52:08 +01:00
|
|
|
|
using Bit.Core.Utilities;
|
2019-05-15 23:37:59 +02:00
|
|
|
|
using Xamarin.Forms;
|
|
|
|
|
|
|
|
|
|
namespace Bit.App.Pages
|
|
|
|
|
{
|
|
|
|
|
public class LockPageViewModel : BaseViewModel
|
|
|
|
|
{
|
2020-09-03 18:30:40 +02:00
|
|
|
|
private readonly IApiService _apiService;
|
2019-05-15 23:37:59 +02:00
|
|
|
|
private readonly IPlatformUtilsService _platformUtilsService;
|
|
|
|
|
private readonly IDeviceActionService _deviceActionService;
|
2020-05-29 18:26:36 +02:00
|
|
|
|
private readonly IVaultTimeoutService _vaultTimeoutService;
|
2019-05-15 23:37:59 +02:00
|
|
|
|
private readonly ICryptoService _cryptoService;
|
|
|
|
|
private readonly IMessagingService _messagingService;
|
2019-06-03 15:58:35 +02:00
|
|
|
|
private readonly IEnvironmentService _environmentService;
|
2019-07-02 14:05:34 +02:00
|
|
|
|
private readonly IStateService _stateService;
|
2020-08-09 03:33:49 +02:00
|
|
|
|
private readonly IBiometricService _biometricService;
|
2021-11-11 02:46:48 +01:00
|
|
|
|
private readonly IKeyConnectorService _keyConnectorService;
|
2022-03-02 18:15:16 +01:00
|
|
|
|
private readonly ILogger _logger;
|
2019-05-15 23:37:59 +02:00
|
|
|
|
|
|
|
|
|
private string _email;
|
|
|
|
|
private bool _showPassword;
|
|
|
|
|
private bool _pinLock;
|
2020-06-08 14:25:13 +02:00
|
|
|
|
private bool _biometricLock;
|
2020-08-09 03:33:49 +02:00
|
|
|
|
private bool _biometricIntegrityValid = true;
|
2020-09-30 16:23:55 +02:00
|
|
|
|
private bool _biometricButtonVisible;
|
2021-11-19 23:25:19 +01:00
|
|
|
|
private bool _usingKeyConnector;
|
2020-06-08 14:25:13 +02:00
|
|
|
|
private string _biometricButtonText;
|
2019-05-17 16:01:45 +02:00
|
|
|
|
private string _loggedInAsText;
|
|
|
|
|
private string _lockedVerifyText;
|
2022-02-23 18:40:17 +01:00
|
|
|
|
private bool _isPinProtected;
|
|
|
|
|
private bool _isPinProtectedWithKey;
|
2019-05-15 23:37:59 +02:00
|
|
|
|
|
|
|
|
|
public LockPageViewModel()
|
|
|
|
|
{
|
2020-09-03 18:30:40 +02:00
|
|
|
|
_apiService = ServiceContainer.Resolve<IApiService>("apiService");
|
2019-05-15 23:37:59 +02:00
|
|
|
|
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
|
|
|
|
|
_deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
|
2020-05-29 18:26:36 +02:00
|
|
|
|
_vaultTimeoutService = ServiceContainer.Resolve<IVaultTimeoutService>("vaultTimeoutService");
|
2019-05-15 23:37:59 +02:00
|
|
|
|
_cryptoService = ServiceContainer.Resolve<ICryptoService>("cryptoService");
|
|
|
|
|
_messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
|
2019-06-03 15:58:35 +02:00
|
|
|
|
_environmentService = ServiceContainer.Resolve<IEnvironmentService>("environmentService");
|
2019-07-02 14:05:34 +02:00
|
|
|
|
_stateService = ServiceContainer.Resolve<IStateService>("stateService");
|
2020-08-09 03:33:49 +02:00
|
|
|
|
_biometricService = ServiceContainer.Resolve<IBiometricService>("biometricService");
|
2021-11-11 02:46:48 +01:00
|
|
|
|
_keyConnectorService = ServiceContainer.Resolve<IKeyConnectorService>("keyConnectorService");
|
2022-03-02 18:15:16 +01:00
|
|
|
|
_logger = ServiceContainer.Resolve<ILogger>("logger");
|
2019-05-15 23:37:59 +02:00
|
|
|
|
|
|
|
|
|
PageTitle = AppResources.VerifyMasterPassword;
|
|
|
|
|
TogglePasswordCommand = new Command(TogglePassword);
|
2019-05-31 18:13:14 +02:00
|
|
|
|
SubmitCommand = new Command(async () => await SubmitAsync());
|
2022-02-23 18:40:17 +01:00
|
|
|
|
|
2022-03-02 18:15:16 +01:00
|
|
|
|
AccountSwitchingOverlayViewModel = new AccountSwitchingOverlayViewModel(_stateService, _messagingService, _logger)
|
2022-02-23 18:40:17 +01:00
|
|
|
|
{
|
|
|
|
|
AllowAddAccountRow = true,
|
|
|
|
|
AllowActiveAccountSelection = true
|
|
|
|
|
};
|
2019-05-15 23:37:59 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool ShowPassword
|
|
|
|
|
{
|
|
|
|
|
get => _showPassword;
|
|
|
|
|
set => SetProperty(ref _showPassword, value,
|
|
|
|
|
additionalPropertyNames: new string[]
|
|
|
|
|
{
|
|
|
|
|
nameof(ShowPasswordIcon)
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool PinLock
|
|
|
|
|
{
|
|
|
|
|
get => _pinLock;
|
|
|
|
|
set => SetProperty(ref _pinLock, value);
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-19 23:25:19 +01:00
|
|
|
|
public bool UsingKeyConnector
|
|
|
|
|
{
|
|
|
|
|
get => _usingKeyConnector;
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-08 14:25:13 +02:00
|
|
|
|
public bool BiometricLock
|
2019-05-16 23:30:07 +02:00
|
|
|
|
{
|
2020-06-08 14:25:13 +02:00
|
|
|
|
get => _biometricLock;
|
|
|
|
|
set => SetProperty(ref _biometricLock, value);
|
2019-05-16 23:30:07 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-08-09 03:33:49 +02:00
|
|
|
|
public bool BiometricIntegrityValid
|
|
|
|
|
{
|
|
|
|
|
get => _biometricIntegrityValid;
|
|
|
|
|
set => SetProperty(ref _biometricIntegrityValid, value);
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-26 03:14:10 +02:00
|
|
|
|
public bool BiometricButtonVisible
|
|
|
|
|
{
|
|
|
|
|
get => _biometricButtonVisible;
|
|
|
|
|
set => SetProperty(ref _biometricButtonVisible, value);
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-08 14:25:13 +02:00
|
|
|
|
public string BiometricButtonText
|
2019-05-17 15:42:20 +02:00
|
|
|
|
{
|
2020-06-08 14:25:13 +02:00
|
|
|
|
get => _biometricButtonText;
|
|
|
|
|
set => SetProperty(ref _biometricButtonText, value);
|
2019-05-17 15:42:20 +02:00
|
|
|
|
}
|
|
|
|
|
|
2019-05-17 16:01:45 +02:00
|
|
|
|
public string LoggedInAsText
|
|
|
|
|
{
|
|
|
|
|
get => _loggedInAsText;
|
|
|
|
|
set => SetProperty(ref _loggedInAsText, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string LockedVerifyText
|
|
|
|
|
{
|
|
|
|
|
get => _lockedVerifyText;
|
|
|
|
|
set => SetProperty(ref _lockedVerifyText, value);
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-23 18:40:17 +01:00
|
|
|
|
public AccountSwitchingOverlayViewModel AccountSwitchingOverlayViewModel { get; }
|
|
|
|
|
|
2019-05-31 18:13:14 +02:00
|
|
|
|
public Command SubmitCommand { get; }
|
2019-05-15 23:37:59 +02:00
|
|
|
|
public Command TogglePasswordCommand { get; }
|
2022-01-21 10:31:03 +01:00
|
|
|
|
public string ShowPasswordIcon => ShowPassword ? BitwardenIcons.EyeSlash : BitwardenIcons.Eye;
|
2019-05-15 23:37:59 +02:00
|
|
|
|
public string MasterPassword { get; set; }
|
|
|
|
|
public string Pin { get; set; }
|
2019-05-17 22:36:29 +02:00
|
|
|
|
public Action UnlockedAction { get; set; }
|
2019-05-15 23:37:59 +02:00
|
|
|
|
|
2021-11-19 23:25:19 +01:00
|
|
|
|
public async Task InitAsync()
|
2019-05-15 23:37:59 +02:00
|
|
|
|
{
|
2022-02-23 18:40:17 +01:00
|
|
|
|
(_isPinProtected, _isPinProtectedWithKey) = await _vaultTimeoutService.IsPinLockSetAsync();
|
|
|
|
|
PinLock = (_isPinProtected && await _stateService.GetPinProtectedKeyAsync() != null) ||
|
|
|
|
|
_isPinProtectedWithKey;
|
2020-09-23 15:02:20 +02:00
|
|
|
|
BiometricLock = await _vaultTimeoutService.IsBiometricLockSetAsync() && await _cryptoService.HasKeyAsync();
|
2021-11-11 02:46:48 +01:00
|
|
|
|
|
|
|
|
|
// Users with key connector and without biometric or pin has no MP to unlock with
|
2021-11-19 23:25:19 +01:00
|
|
|
|
_usingKeyConnector = await _keyConnectorService.GetUsesKeyConnector();
|
2022-01-18 15:52:08 +01:00
|
|
|
|
if (_usingKeyConnector && !(BiometricLock || PinLock))
|
2021-11-11 02:46:48 +01:00
|
|
|
|
{
|
|
|
|
|
await _vaultTimeoutService.LogOutAsync();
|
2022-02-11 19:46:17 +01:00
|
|
|
|
return;
|
2021-11-11 02:46:48 +01:00
|
|
|
|
}
|
2022-02-23 18:40:17 +01:00
|
|
|
|
_email = await _stateService.GetEmailAsync();
|
2022-02-11 19:46:17 +01:00
|
|
|
|
if (string.IsNullOrWhiteSpace(_email))
|
|
|
|
|
{
|
|
|
|
|
await _vaultTimeoutService.LogOutAsync();
|
2022-03-02 18:15:16 +01:00
|
|
|
|
_logger.Exception(new NullReferenceException("Email not found in storage"));
|
2022-02-11 19:46:17 +01:00
|
|
|
|
return;
|
|
|
|
|
}
|
2022-02-24 14:27:08 +01:00
|
|
|
|
var webVault = _environmentService.GetWebVaultUrl(true);
|
2020-03-28 14:16:28 +01:00
|
|
|
|
if (string.IsNullOrWhiteSpace(webVault))
|
2019-06-03 15:58:35 +02:00
|
|
|
|
{
|
|
|
|
|
webVault = "https://bitwarden.com";
|
|
|
|
|
}
|
|
|
|
|
var webVaultHostname = CoreHelpers.GetHostname(webVault);
|
|
|
|
|
LoggedInAsText = string.Format(AppResources.LoggedInAsOn, _email, webVaultHostname);
|
2020-03-28 14:16:28 +01:00
|
|
|
|
if (PinLock)
|
2019-05-17 16:01:45 +02:00
|
|
|
|
{
|
|
|
|
|
PageTitle = AppResources.VerifyPIN;
|
|
|
|
|
LockedVerifyText = AppResources.VaultLockedPIN;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2021-11-19 23:25:19 +01:00
|
|
|
|
if (_usingKeyConnector)
|
|
|
|
|
{
|
|
|
|
|
PageTitle = AppResources.UnlockVault;
|
|
|
|
|
LockedVerifyText = AppResources.VaultLockedIdentity;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
PageTitle = AppResources.VerifyMasterPassword;
|
|
|
|
|
LockedVerifyText = AppResources.VaultLockedMasterPassword;
|
|
|
|
|
}
|
2019-05-17 16:01:45 +02:00
|
|
|
|
}
|
2019-05-16 23:30:07 +02:00
|
|
|
|
|
2020-06-08 14:25:13 +02:00
|
|
|
|
if (BiometricLock)
|
2019-05-16 23:30:07 +02:00
|
|
|
|
{
|
2020-09-26 03:14:10 +02:00
|
|
|
|
BiometricIntegrityValid = await _biometricService.ValidateIntegrityAsync();
|
|
|
|
|
if (!_biometricIntegrityValid)
|
|
|
|
|
{
|
|
|
|
|
BiometricButtonVisible = false;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
BiometricButtonVisible = true;
|
2020-06-08 14:25:13 +02:00
|
|
|
|
BiometricButtonText = AppResources.UseBiometricsToUnlock;
|
|
|
|
|
if (Device.RuntimePlatform == Device.iOS)
|
2019-10-23 15:24:34 +02:00
|
|
|
|
{
|
2020-06-08 14:25:13 +02:00
|
|
|
|
var supportsFace = await _deviceActionService.SupportsFaceBiometricAsync();
|
|
|
|
|
BiometricButtonText = supportsFace ? AppResources.UseFaceIDToUnlock :
|
|
|
|
|
AppResources.UseFingerprintToUnlock;
|
2019-10-23 15:24:34 +02:00
|
|
|
|
}
|
2021-11-19 23:25:19 +01:00
|
|
|
|
|
2019-05-16 23:30:07 +02:00
|
|
|
|
}
|
2019-05-15 23:37:59 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task SubmitAsync()
|
|
|
|
|
{
|
2020-03-28 14:16:28 +01:00
|
|
|
|
if (PinLock && string.IsNullOrWhiteSpace(Pin))
|
2019-05-15 23:37:59 +02:00
|
|
|
|
{
|
|
|
|
|
await Page.DisplayAlert(AppResources.AnErrorHasOccurred,
|
|
|
|
|
string.Format(AppResources.ValidationFieldRequired, AppResources.PIN),
|
|
|
|
|
AppResources.Ok);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2020-03-28 14:16:28 +01:00
|
|
|
|
if (!PinLock && string.IsNullOrWhiteSpace(MasterPassword))
|
2019-05-15 23:37:59 +02:00
|
|
|
|
{
|
|
|
|
|
await Page.DisplayAlert(AppResources.AnErrorHasOccurred,
|
|
|
|
|
string.Format(AppResources.ValidationFieldRequired, AppResources.MasterPassword),
|
|
|
|
|
AppResources.Ok);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-31 05:48:39 +02:00
|
|
|
|
ShowPassword = false;
|
2022-02-23 18:40:17 +01:00
|
|
|
|
var kdf = await _stateService.GetKdfTypeAsync();
|
|
|
|
|
var kdfIterations = await _stateService.GetKdfIterationsAsync();
|
2019-05-15 23:37:59 +02:00
|
|
|
|
|
2020-03-28 14:16:28 +01:00
|
|
|
|
if (PinLock)
|
2019-05-15 23:37:59 +02:00
|
|
|
|
{
|
|
|
|
|
var failed = true;
|
|
|
|
|
try
|
|
|
|
|
{
|
2022-02-23 18:40:17 +01:00
|
|
|
|
if (_isPinProtected)
|
2019-05-15 23:37:59 +02:00
|
|
|
|
{
|
2019-09-20 22:43:03 +02:00
|
|
|
|
var key = await _cryptoService.MakeKeyFromPinAsync(Pin, _email,
|
|
|
|
|
kdf.GetValueOrDefault(KdfType.PBKDF2_SHA256), kdfIterations.GetValueOrDefault(5000),
|
2022-02-23 18:40:17 +01:00
|
|
|
|
await _stateService.GetPinProtectedKeyAsync());
|
2019-09-20 22:43:03 +02:00
|
|
|
|
var encKey = await _cryptoService.GetEncKeyAsync(key);
|
2022-02-23 18:40:17 +01:00
|
|
|
|
var protectedPin = await _stateService.GetProtectedPinAsync();
|
2021-04-21 22:27:14 +02:00
|
|
|
|
var decPin = await _cryptoService.DecryptToUtf8Async(new EncString(protectedPin), encKey);
|
2019-05-15 23:37:59 +02:00
|
|
|
|
failed = decPin != Pin;
|
2020-03-28 14:16:28 +01:00
|
|
|
|
if (!failed)
|
2019-05-15 23:37:59 +02:00
|
|
|
|
{
|
2019-05-31 05:48:39 +02:00
|
|
|
|
Pin = string.Empty;
|
2021-06-09 16:03:05 +02:00
|
|
|
|
await AppHelpers.ResetInvalidUnlockAttemptsAsync();
|
2019-09-20 22:43:03 +02:00
|
|
|
|
await SetKeyAndContinueAsync(key);
|
2019-05-15 23:37:59 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
var key = await _cryptoService.MakeKeyFromPinAsync(Pin, _email,
|
|
|
|
|
kdf.GetValueOrDefault(KdfType.PBKDF2_SHA256), kdfIterations.GetValueOrDefault(5000));
|
|
|
|
|
failed = false;
|
2019-05-31 05:48:39 +02:00
|
|
|
|
Pin = string.Empty;
|
2021-06-09 16:03:05 +02:00
|
|
|
|
await AppHelpers.ResetInvalidUnlockAttemptsAsync();
|
2019-05-15 23:37:59 +02:00
|
|
|
|
await SetKeyAndContinueAsync(key);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch
|
|
|
|
|
{
|
|
|
|
|
failed = true;
|
|
|
|
|
}
|
2020-03-28 14:16:28 +01:00
|
|
|
|
if (failed)
|
2019-05-15 23:37:59 +02:00
|
|
|
|
{
|
2021-06-09 16:03:05 +02:00
|
|
|
|
var invalidUnlockAttempts = await AppHelpers.IncrementInvalidUnlockAttemptsAsync();
|
|
|
|
|
if (invalidUnlockAttempts >= 5)
|
2019-05-15 23:37:59 +02:00
|
|
|
|
{
|
|
|
|
|
_messagingService.Send("logout");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
await _platformUtilsService.ShowDialogAsync(AppResources.InvalidPIN,
|
|
|
|
|
AppResources.AnErrorHasOccurred);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
var key = await _cryptoService.MakeKeyAsync(MasterPassword, _email, kdf, kdfIterations);
|
2021-06-14 23:39:34 +02:00
|
|
|
|
var storedKeyHash = await _cryptoService.GetKeyHashAsync();
|
2020-09-03 18:30:40 +02:00
|
|
|
|
var passwordValid = false;
|
2022-04-26 17:21:17 +02:00
|
|
|
|
|
2021-06-14 23:39:34 +02:00
|
|
|
|
if (storedKeyHash != null)
|
2019-06-01 05:46:22 +02:00
|
|
|
|
{
|
2021-06-14 23:39:34 +02:00
|
|
|
|
passwordValid = await _cryptoService.CompareAndUpdateKeyHashAsync(MasterPassword, key);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
await _deviceActionService.ShowLoadingAsync(AppResources.Loading);
|
|
|
|
|
var keyHash = await _cryptoService.HashPasswordAsync(MasterPassword, key, HashPurpose.ServerAuthorization);
|
|
|
|
|
var request = new PasswordVerificationRequest();
|
|
|
|
|
request.MasterPasswordHash = keyHash;
|
|
|
|
|
try
|
2019-06-01 05:46:22 +02:00
|
|
|
|
{
|
2021-06-14 23:39:34 +02:00
|
|
|
|
await _apiService.PostAccountVerifyPasswordAsync(request);
|
|
|
|
|
passwordValid = true;
|
|
|
|
|
var localKeyHash = await _cryptoService.HashPasswordAsync(MasterPassword, key, HashPurpose.LocalAuthorization);
|
|
|
|
|
await _cryptoService.SetKeyHashAsync(localKeyHash);
|
2020-09-03 18:30:40 +02:00
|
|
|
|
}
|
2021-06-14 23:39:34 +02:00
|
|
|
|
catch (Exception e)
|
2020-09-03 18:30:40 +02:00
|
|
|
|
{
|
2021-06-14 23:39:34 +02:00
|
|
|
|
System.Diagnostics.Debug.WriteLine(">>> {0}: {1}", e.GetType(), e.StackTrace);
|
2019-06-01 05:46:22 +02:00
|
|
|
|
}
|
2021-06-14 23:39:34 +02:00
|
|
|
|
await _deviceActionService.HideLoadingAsync();
|
2019-06-01 05:46:22 +02:00
|
|
|
|
}
|
2020-09-03 18:30:40 +02:00
|
|
|
|
if (passwordValid)
|
2019-05-15 23:37:59 +02:00
|
|
|
|
{
|
2022-02-23 18:40:17 +01:00
|
|
|
|
if (_isPinProtected)
|
2019-09-20 22:43:03 +02:00
|
|
|
|
{
|
2022-02-23 18:40:17 +01:00
|
|
|
|
var protectedPin = await _stateService.GetProtectedPinAsync();
|
2019-09-20 22:43:03 +02:00
|
|
|
|
var encKey = await _cryptoService.GetEncKeyAsync(key);
|
2021-04-21 22:27:14 +02:00
|
|
|
|
var decPin = await _cryptoService.DecryptToUtf8Async(new EncString(protectedPin), encKey);
|
2019-09-20 22:43:03 +02:00
|
|
|
|
var pinKey = await _cryptoService.MakePinKeyAysnc(decPin, _email,
|
|
|
|
|
kdf.GetValueOrDefault(KdfType.PBKDF2_SHA256), kdfIterations.GetValueOrDefault(5000));
|
2022-02-23 18:40:17 +01:00
|
|
|
|
await _stateService.SetPinProtectedKeyAsync(await _cryptoService.EncryptAsync(key.Key, pinKey));
|
2019-09-20 22:43:03 +02:00
|
|
|
|
}
|
2019-05-31 05:48:39 +02:00
|
|
|
|
MasterPassword = string.Empty;
|
2021-06-09 16:03:05 +02:00
|
|
|
|
await AppHelpers.ResetInvalidUnlockAttemptsAsync();
|
2019-05-15 23:37:59 +02:00
|
|
|
|
await SetKeyAndContinueAsync(key);
|
2020-08-09 03:33:49 +02:00
|
|
|
|
|
|
|
|
|
// Re-enable biometrics
|
|
|
|
|
if (BiometricLock & !BiometricIntegrityValid)
|
|
|
|
|
{
|
|
|
|
|
await _biometricService.SetupBiometricAsync();
|
|
|
|
|
}
|
2019-05-15 23:37:59 +02:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2021-06-09 16:03:05 +02:00
|
|
|
|
var invalidUnlockAttempts = await AppHelpers.IncrementInvalidUnlockAttemptsAsync();
|
|
|
|
|
if (invalidUnlockAttempts >= 5)
|
|
|
|
|
{
|
|
|
|
|
_messagingService.Send("logout");
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-05-15 23:37:59 +02:00
|
|
|
|
await _platformUtilsService.ShowDialogAsync(AppResources.InvalidMasterPassword,
|
|
|
|
|
AppResources.AnErrorHasOccurred);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task LogOutAsync()
|
|
|
|
|
{
|
|
|
|
|
var confirmed = await _platformUtilsService.ShowDialogAsync(AppResources.LogoutConfirmation,
|
|
|
|
|
AppResources.LogOut, AppResources.Yes, AppResources.Cancel);
|
2020-03-28 14:16:28 +01:00
|
|
|
|
if (confirmed)
|
2019-05-15 23:37:59 +02:00
|
|
|
|
{
|
|
|
|
|
_messagingService.Send("logout");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void TogglePassword()
|
|
|
|
|
{
|
|
|
|
|
ShowPassword = !ShowPassword;
|
|
|
|
|
var page = (Page as LockPage);
|
|
|
|
|
var entry = PinLock ? page.PinEntry : page.MasterPasswordEntry;
|
2021-10-15 16:56:12 +02:00
|
|
|
|
var str = PinLock ? Pin : MasterPassword;
|
2019-05-15 23:37:59 +02:00
|
|
|
|
entry.Focus();
|
2021-10-15 16:56:12 +02:00
|
|
|
|
entry.CursorPosition = String.IsNullOrEmpty(str) ? 0 : str.Length;
|
2019-05-15 23:37:59 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-06-08 14:25:13 +02:00
|
|
|
|
public async Task PromptBiometricAsync()
|
2019-05-17 15:42:20 +02:00
|
|
|
|
{
|
2020-08-09 03:33:49 +02:00
|
|
|
|
BiometricIntegrityValid = await _biometricService.ValidateIntegrityAsync();
|
|
|
|
|
if (!BiometricLock || !BiometricIntegrityValid)
|
2019-06-07 16:12:11 +02:00
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-10-23 15:11:48 +02:00
|
|
|
|
var success = await _platformUtilsService.AuthenticateBiometricAsync(null,
|
2019-06-07 16:12:11 +02:00
|
|
|
|
PinLock ? AppResources.PIN : AppResources.MasterPassword, () =>
|
|
|
|
|
{
|
|
|
|
|
var page = Page as LockPage;
|
2020-03-28 14:16:28 +01:00
|
|
|
|
if (PinLock)
|
2019-05-17 15:42:20 +02:00
|
|
|
|
{
|
2019-06-07 16:12:11 +02:00
|
|
|
|
page.PinEntry.Focus();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
page.MasterPasswordEntry.Focus();
|
|
|
|
|
}
|
|
|
|
|
});
|
2022-03-01 20:04:17 +01:00
|
|
|
|
await _stateService.SetBiometricLockedAsync(!success);
|
2020-03-28 14:16:28 +01:00
|
|
|
|
if (success)
|
2019-05-17 15:42:20 +02:00
|
|
|
|
{
|
2019-07-02 14:05:34 +02:00
|
|
|
|
await DoContinueAsync();
|
2019-05-17 15:42:20 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-15 23:37:59 +02:00
|
|
|
|
private async Task SetKeyAndContinueAsync(SymmetricCryptoKey key)
|
|
|
|
|
{
|
2019-09-20 22:43:03 +02:00
|
|
|
|
var hasKey = await _cryptoService.HasKeyAsync();
|
2020-03-28 14:16:28 +01:00
|
|
|
|
if (!hasKey)
|
2019-05-17 15:42:20 +02:00
|
|
|
|
{
|
|
|
|
|
await _cryptoService.SetKeyAsync(key);
|
|
|
|
|
}
|
2019-07-02 14:05:34 +02:00
|
|
|
|
await DoContinueAsync();
|
2019-05-15 23:37:59 +02:00
|
|
|
|
}
|
|
|
|
|
|
2019-07-02 14:05:34 +02:00
|
|
|
|
private async Task DoContinueAsync()
|
2019-05-15 23:37:59 +02:00
|
|
|
|
{
|
2022-03-01 20:04:17 +01:00
|
|
|
|
await _stateService.SetBiometricLockedAsync(false);
|
2019-05-15 23:37:59 +02:00
|
|
|
|
_messagingService.Send("unlocked");
|
2019-05-17 22:36:29 +02:00
|
|
|
|
UnlockedAction?.Invoke();
|
2019-05-15 23:37:59 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|