1
0
mirror of https://github.com/bitwarden/mobile.git synced 2024-06-29 11:05:52 +02:00

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

@ -8,7 +8,7 @@
xmlns:u="clr-namespace:Bit.App.Utilities" xmlns:u="clr-namespace:Bit.App.Utilities"
x:DataType="pages:LockPageViewModel" x:DataType="pages:LockPageViewModel"
Title="{Binding PageTitle}"> Title="{Binding PageTitle}">
<ContentPage.BindingContext> <ContentPage.BindingContext>
<pages:LockPageViewModel /> <pages:LockPageViewModel />
</ContentPage.BindingContext> </ContentPage.BindingContext>
@ -87,6 +87,8 @@
</Grid> </Grid>
</StackLayout> </StackLayout>
<StackLayout Padding="10, 0"> <StackLayout Padding="10, 0">
<Button Text="{Binding FingerprintButtonText}" Clicked="Fingerprint_Clicked"
IsVisible="{Binding FingerprintLock}"></Button>
<Button Text="{u:I18n LogOut}" Clicked="LogOut_Clicked"></Button> <Button Text="{u:I18n LogOut}" Clicked="LogOut_Clicked"></Button>
</StackLayout> </StackLayout>
</StackLayout> </StackLayout>

View File

@ -59,5 +59,13 @@ namespace Bit.App.Pages
await _vm.LogOutAsync(); 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 IUserService _userService;
private readonly IMessagingService _messagingService; private readonly IMessagingService _messagingService;
private bool _hasKey;
private string _email; private string _email;
private bool _showPassword; private bool _showPassword;
private bool _pinLock; private bool _pinLock;
private bool _fingerprintLock; private bool _fingerprintLock;
private string _fingerprintButtonText;
private int _invalidPinAttempts = 0; private int _invalidPinAttempts = 0;
private Tuple<bool, bool> _pinSet; private Tuple<bool, bool> _pinSet;
@ -64,6 +66,12 @@ namespace Bit.App.Pages
set => SetProperty(ref _fingerprintLock, value); set => SetProperty(ref _fingerprintLock, value);
} }
public string FingerprintButtonText
{
get => _fingerprintButtonText;
set => SetProperty(ref _fingerprintButtonText, value);
}
public Command TogglePasswordCommand { get; } public Command TogglePasswordCommand { get; }
public string ShowPasswordIcon => ShowPassword ? "" : ""; public string ShowPasswordIcon => ShowPassword ? "" : "";
public string MasterPassword { get; set; } public string MasterPassword { get; set; }
@ -72,25 +80,19 @@ namespace Bit.App.Pages
public async Task InitAsync() public async Task InitAsync()
{ {
_pinSet = await _lockService.IsPinLockSetAsync(); _pinSet = await _lockService.IsPinLockSetAsync();
var hasKey = await _cryptoService.HasKeyAsync(); _hasKey = await _cryptoService.HasKeyAsync();
PinLock = (_pinSet.Item1 && hasKey) || _pinSet.Item2; PinLock = (_pinSet.Item1 && _hasKey) || _pinSet.Item2;
FingerprintLock = await _lockService.IsFingerprintLockSetAsync(); FingerprintLock = await _lockService.IsFingerprintLockSetAsync();
_email = await _userService.GetEmailAsync(); _email = await _userService.GetEmailAsync();
PageTitle = PinLock ? AppResources.VerifyPIN : AppResources.VerifyMasterPassword; PageTitle = PinLock ? AppResources.VerifyPIN : AppResources.VerifyMasterPassword;
if(FingerprintLock) if(FingerprintLock)
{ {
FingerprintButtonText = AppResources.UseFingerprintToUnlock; // TODO: FaceID text
var tasks = Task.Run(async () => var tasks = Task.Run(async () =>
{ {
await Task.Delay(500); await Task.Delay(500);
Device.BeginInvokeOnMainThread(async () => { Device.BeginInvokeOnMainThread(async () => await PromptFingerprintAsync());
var success = await _platformUtilsService.AuthenticateFingerprintAsync();
_lockService.FingerprintLocked = !success;
if(success)
{
DoContinue();
}
});
}); });
} }
} }
@ -190,9 +192,34 @@ namespace Bit.App.Pages
entry.Focus(); 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) private async Task SetKeyAndContinueAsync(SymmetricCryptoKey key)
{ {
await _cryptoService.SetKeyAsync(key); if(!_hasKey)
{
await _cryptoService.SetKeyAsync(key);
}
DoContinue(); 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 try
{ {
@ -212,13 +213,18 @@ namespace Bit.App.Services
var fingerprintRequest = new AuthenticationRequestConfiguration(text) var fingerprintRequest = new AuthenticationRequestConfiguration(text)
{ {
AllowAlternativeAuthentication = true, AllowAlternativeAuthentication = true,
CancelTitle = AppResources.Cancel CancelTitle = AppResources.Cancel,
FallbackTitle = fallbackText
}; };
var result = await CrossFingerprint.Current.AuthenticateAsync(fingerprintRequest); var result = await CrossFingerprint.Current.AuthenticateAsync(fingerprintRequest);
if(result.Authenticated) if(result.Authenticated)
{ {
return true; return true;
} }
else if(result.Status == FingerprintAuthenticationResultStatus.FallbackRequested)
{
fallback?.Invoke();
}
} }
catch { } catch { }
return false; return false;

View File

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