mirror of
https://github.com/bitwarden/mobile.git
synced 2024-12-24 16:38:22 +01:00
fingerprint locking
This commit is contained in:
parent
22a0b262e1
commit
5761b47073
@ -147,6 +147,7 @@ namespace Bit.App
|
||||
_passwordGenerationService.ClearAsync(),
|
||||
_lockService.ClearAsync());
|
||||
_lockService.PinLocked = false;
|
||||
_lockService.FingerprintLocked = true;
|
||||
_searchService.ClearIndex();
|
||||
_authService.LogOut(() =>
|
||||
{
|
||||
|
@ -28,7 +28,7 @@ namespace Bit.App.Pages
|
||||
{
|
||||
RequestFocus(PinEntry);
|
||||
}
|
||||
else
|
||||
else if(!_vm.FingerprintLock)
|
||||
{
|
||||
RequestFocus(MasterPasswordEntry);
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ namespace Bit.App.Pages
|
||||
private string _email;
|
||||
private bool _showPassword;
|
||||
private bool _pinLock;
|
||||
private bool _fingerprintLock;
|
||||
private int _invalidPinAttempts = 0;
|
||||
private Tuple<bool, bool> _pinSet;
|
||||
|
||||
@ -57,6 +58,12 @@ namespace Bit.App.Pages
|
||||
set => SetProperty(ref _pinLock, value);
|
||||
}
|
||||
|
||||
public bool FingerprintLock
|
||||
{
|
||||
get => _fingerprintLock;
|
||||
set => SetProperty(ref _fingerprintLock, value);
|
||||
}
|
||||
|
||||
public Command TogglePasswordCommand { get; }
|
||||
public string ShowPasswordIcon => ShowPassword ? "" : "";
|
||||
public string MasterPassword { get; set; }
|
||||
@ -67,8 +74,25 @@ namespace Bit.App.Pages
|
||||
_pinSet = await _lockService.IsPinLockSetAsync();
|
||||
var hasKey = await _cryptoService.HasKeyAsync();
|
||||
PinLock = (_pinSet.Item1 && hasKey) || _pinSet.Item2;
|
||||
FingerprintLock = await _lockService.IsFingerprintLockSetAsync();
|
||||
_email = await _userService.GetEmailAsync();
|
||||
PageTitle = PinLock ? AppResources.VerifyPIN : AppResources.VerifyMasterPassword;
|
||||
|
||||
if(FingerprintLock)
|
||||
{
|
||||
var tasks = Task.Run(async () =>
|
||||
{
|
||||
await Task.Delay(500);
|
||||
Device.BeginInvokeOnMainThread(async () => {
|
||||
var success = await _platformUtilsService.AuthenticateFingerprintAsync();
|
||||
_lockService.FingerprintLocked = !success;
|
||||
if(success)
|
||||
{
|
||||
DoContinue();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public async Task SubmitAsync()
|
||||
|
@ -102,6 +102,11 @@ namespace Bit.App.Pages
|
||||
{
|
||||
await _vm.UpdatePinAsync();
|
||||
}
|
||||
else if(item.Name.Contains(AppResources.Fingerprint) || item.Name.Contains(AppResources.TouchID) ||
|
||||
item.Name.Contains(AppResources.FaceID))
|
||||
{
|
||||
await _vm.UpdateFingerprintAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ namespace Bit.App.Pages
|
||||
_lockOptionValue = _lockOptions.FirstOrDefault(o => o.Value == option).Key;
|
||||
var pinSet = await _lockService.IsPinLockSetAsync();
|
||||
_pin = pinSet.Item1 || pinSet.Item2;
|
||||
// TODO: Fingerprint
|
||||
_fingerprint = await _lockService.IsFingerprintLockSetAsync();
|
||||
BuildList();
|
||||
}
|
||||
|
||||
@ -238,7 +238,21 @@ namespace Bit.App.Pages
|
||||
await _storageService.RemoveAsync(Constants.PinProtectedKey);
|
||||
await _storageService.RemoveAsync(Constants.ProtectedPin);
|
||||
}
|
||||
BuildList();
|
||||
}
|
||||
|
||||
public async Task UpdateFingerprintAsync()
|
||||
{
|
||||
_fingerprint = !_fingerprint;
|
||||
if(_fingerprint)
|
||||
{
|
||||
await _storageService.SaveAsync(Constants.FingerprintUnlockKey, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
await _storageService.RemoveAsync(Constants.FingerprintUnlockKey);
|
||||
}
|
||||
await _cryptoService.ToggleKeyAsync();
|
||||
BuildList();
|
||||
}
|
||||
|
||||
|
@ -200,29 +200,25 @@ namespace Bit.App.Services
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> AuthenticateFingerprintAsync(string text = null, Action fallback = null)
|
||||
public async Task<bool> AuthenticateFingerprintAsync(string text = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if(text == null)
|
||||
{
|
||||
text = AppResources.FingerprintDirection;
|
||||
// TODO: face id direction
|
||||
}
|
||||
var fingerprintRequest = new AuthenticationRequestConfiguration(text)
|
||||
{
|
||||
AllowAlternativeAuthentication = true,
|
||||
CancelTitle = AppResources.Cancel,
|
||||
FallbackTitle = AppResources.LogOut
|
||||
CancelTitle = AppResources.Cancel
|
||||
};
|
||||
var result = await CrossFingerprint.Current.AuthenticateAsync(fingerprintRequest);
|
||||
if(result.Authenticated)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if(result.Status == FingerprintAuthenticationResultStatus.FallbackRequested)
|
||||
{
|
||||
fallback?.Invoke();
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
return false;
|
||||
|
@ -6,11 +6,13 @@ namespace Bit.Core.Abstractions
|
||||
public interface ILockService
|
||||
{
|
||||
bool PinLocked { get; set; }
|
||||
bool FingerprintLocked { get; set; }
|
||||
|
||||
Task CheckLockAsync();
|
||||
Task ClearAsync();
|
||||
Task<bool> IsLockedAsync();
|
||||
Task<Tuple<bool, bool>> IsPinLockSetAsync();
|
||||
Task<bool> IsFingerprintLockSetAsync();
|
||||
Task LockAsync(bool allowSoftLock = false);
|
||||
Task SetLockOptionAsync(int? lockOption);
|
||||
}
|
||||
|
@ -27,6 +27,6 @@ namespace Bit.Core.Abstractions
|
||||
bool SupportsU2f();
|
||||
bool SupportsDuo();
|
||||
Task<bool> SupportsFingerprintAsync();
|
||||
Task<bool> AuthenticateFingerprintAsync(string text = null, Action fallback = null);
|
||||
Task<bool> AuthenticateFingerprintAsync(string text = null);
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@
|
||||
public const string iOSAppProtocol = "iosapp://";
|
||||
public static string LockOptionKey = "lockOption";
|
||||
public static string LastActiveKey = "lastActive";
|
||||
public static string FingerprintUnlockKey = "fingerprintUnlock";
|
||||
public static string ProtectedPin = "protectedPin";
|
||||
public static string PinProtectedKey = "pinProtectedKey";
|
||||
public static string DefaultUriMatch = "defaultUriMatch";
|
||||
|
@ -47,7 +47,8 @@ namespace Bit.Core.Services
|
||||
{
|
||||
_key = key;
|
||||
var option = await _storageService.GetAsync<int?>(Constants.LockOptionKey);
|
||||
if(option.HasValue)
|
||||
var fingerprint = await _storageService.GetAsync<bool?>(Constants.FingerprintUnlockKey);
|
||||
if(option.HasValue && !fingerprint.GetValueOrDefault())
|
||||
{
|
||||
// If we have a lock option set, we do not store the key
|
||||
return;
|
||||
@ -349,7 +350,8 @@ namespace Bit.Core.Services
|
||||
{
|
||||
var key = await GetKeyAsync();
|
||||
var option = await _storageService.GetAsync<int?>(Constants.LockOptionKey);
|
||||
if(option != null || option == 0)
|
||||
var fingerprint = await _storageService.GetAsync<bool?>(Constants.FingerprintUnlockKey);
|
||||
if(!fingerprint.GetValueOrDefault() && (option != null || option == 0))
|
||||
{
|
||||
await ClearKeyAsync();
|
||||
_key = key;
|
||||
|
@ -39,15 +39,27 @@ namespace Bit.Core.Services
|
||||
}
|
||||
|
||||
public bool PinLocked { get; set; }
|
||||
public bool FingerprintLocked { get; set; } = true;
|
||||
|
||||
// TODO: init timer?
|
||||
|
||||
public async Task<bool> IsLockedAsync()
|
||||
{
|
||||
var hasKey = await _cryptoService.HasKeyAsync();
|
||||
if(hasKey && PinLocked)
|
||||
if(hasKey)
|
||||
{
|
||||
return true;
|
||||
if(PinLocked)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
var fingerprintSet = await IsFingerprintLockSetAsync();
|
||||
if(fingerprintSet && FingerprintLocked)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return !hasKey;
|
||||
}
|
||||
@ -102,6 +114,13 @@ namespace Bit.Core.Services
|
||||
if(pinSet.Item1)
|
||||
{
|
||||
PinLocked = true;
|
||||
}
|
||||
if(await IsFingerprintLockSetAsync())
|
||||
{
|
||||
FingerprintLocked = true;
|
||||
}
|
||||
if(FingerprintLocked || PinLocked)
|
||||
{
|
||||
_messagingService.Send("locked");
|
||||
// TODO: locked callback?
|
||||
return;
|
||||
@ -134,6 +153,12 @@ namespace Bit.Core.Services
|
||||
return new Tuple<bool, bool>(protectedPin != null, pinProtectedKey != null);
|
||||
}
|
||||
|
||||
public async Task<bool> IsFingerprintLockSetAsync()
|
||||
{
|
||||
var fingerprintLock = await _storageService.GetAsync<bool?>(Constants.FingerprintUnlockKey);
|
||||
return fingerprintLock.GetValueOrDefault();
|
||||
}
|
||||
|
||||
public async Task ClearAsync()
|
||||
{
|
||||
await _storageService.RemoveAsync(Constants.ProtectedPin);
|
||||
|
Loading…
Reference in New Issue
Block a user