mirror of
https://github.com/bitwarden/mobile.git
synced 2024-11-27 12:26:31 +01:00
fingerprint unlock
This commit is contained in:
parent
a7ad89471a
commit
4aa1209bc7
@ -8,7 +8,7 @@
|
||||
xmlns:u="clr-namespace:Bit.App.Utilities"
|
||||
x:DataType="pages:LockPageViewModel"
|
||||
Title="{Binding PageTitle}">
|
||||
|
||||
|
||||
<ContentPage.BindingContext>
|
||||
<pages:LockPageViewModel />
|
||||
</ContentPage.BindingContext>
|
||||
@ -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>
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user