fingerprint unlock

This commit is contained in:
Kyle Spearrin 2019-05-17 09:42:20 -04:00
parent a7ad89471a
commit 4aa1209bc7
5 changed files with 58 additions and 15 deletions

View file

@ -87,6 +87,8 @@
</Grid>
</StackLayout>
<StackLayout Padding="10, 0">
<Button Text="{Binding FingerprintButtonText}" Clicked="Fingerprint_Clicked"
IsVisible="{Binding FingerprintLock}"></Button>
<Button Text="{u:I18n LogOut}" Clicked="LogOut_Clicked"></Button>
</StackLayout>
</StackLayout>

View file

@ -59,5 +59,13 @@ namespace Bit.App.Pages
await _vm.LogOutAsync();
}
}
private async void Fingerprint_Clicked(object sender, EventArgs e)
{
if(DoOnce())
{
await _vm.PromptFingerprintAsync();
}
}
}
}

View file

@ -21,10 +21,12 @@ namespace Bit.App.Pages
private readonly IUserService _userService;
private readonly IMessagingService _messagingService;
private bool _hasKey;
private string _email;
private bool _showPassword;
private bool _pinLock;
private bool _fingerprintLock;
private string _fingerprintButtonText;
private int _invalidPinAttempts = 0;
private Tuple<bool, bool> _pinSet;
@ -64,6 +66,12 @@ namespace Bit.App.Pages
set => SetProperty(ref _fingerprintLock, value);
}
public string FingerprintButtonText
{
get => _fingerprintButtonText;
set => SetProperty(ref _fingerprintButtonText, value);
}
public Command TogglePasswordCommand { get; }
public string ShowPasswordIcon => ShowPassword ? "" : "";
public string MasterPassword { get; set; }
@ -72,25 +80,19 @@ namespace Bit.App.Pages
public async Task InitAsync()
{
_pinSet = await _lockService.IsPinLockSetAsync();
var hasKey = await _cryptoService.HasKeyAsync();
PinLock = (_pinSet.Item1 && hasKey) || _pinSet.Item2;
_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)
{
FingerprintButtonText = AppResources.UseFingerprintToUnlock; // TODO: FaceID text
var tasks = Task.Run(async () =>
{
await Task.Delay(500);
Device.BeginInvokeOnMainThread(async () => {
var success = await _platformUtilsService.AuthenticateFingerprintAsync();
_lockService.FingerprintLocked = !success;
if(success)
{
DoContinue();
}
});
Device.BeginInvokeOnMainThread(async () => await PromptFingerprintAsync());
});
}
}
@ -190,9 +192,34 @@ namespace Bit.App.Pages
entry.Focus();
}
public async Task PromptFingerprintAsync()
{
var success = await _platformUtilsService.AuthenticateFingerprintAsync(null,
PinLock ? AppResources.PIN : AppResources.MasterPassword, () =>
{
var page = Page as LockPage;
if(PinLock)
{
page.PinEntry.Focus();
}
else
{
page.MasterPasswordEntry.Focus();
}
});
_lockService.FingerprintLocked = !success;
if(success)
{
DoContinue();
}
}
private async Task SetKeyAndContinueAsync(SymmetricCryptoKey key)
{
await _cryptoService.SetKeyAsync(key);
if(!_hasKey)
{
await _cryptoService.SetKeyAsync(key);
}
DoContinue();
}

View file

@ -200,7 +200,8 @@ namespace Bit.App.Services
}
}
public async Task<bool> AuthenticateFingerprintAsync(string text = null)
public async Task<bool> AuthenticateFingerprintAsync(string text = null, string fallbackText = null,
Action fallback = null)
{
try
{
@ -212,13 +213,18 @@ namespace Bit.App.Services
var fingerprintRequest = new AuthenticationRequestConfiguration(text)
{
AllowAlternativeAuthentication = true,
CancelTitle = AppResources.Cancel
CancelTitle = AppResources.Cancel,
FallbackTitle = fallbackText
};
var result = await CrossFingerprint.Current.AuthenticateAsync(fingerprintRequest);
if(result.Authenticated)
{
return true;
}
else if(result.Status == FingerprintAuthenticationResultStatus.FallbackRequested)
{
fallback?.Invoke();
}
}
catch { }
return false;

View file

@ -27,6 +27,6 @@ namespace Bit.Core.Abstractions
bool SupportsU2f();
bool SupportsDuo();
Task<bool> SupportsFingerprintAsync();
Task<bool> AuthenticateFingerprintAsync(string text = null);
Task<bool> AuthenticateFingerprintAsync(string text = null, string fallbackText = null, Action fallback = null);
}
}