1
0
mirror of https://github.com/bitwarden/mobile synced 2026-01-01 16:13:15 +00:00

use native biomatrics on Android

This commit is contained in:
Kyle Spearrin
2019-10-23 09:11:48 -04:00
parent aed3ec5474
commit 4b989b01e9
11 changed files with 199 additions and 52 deletions

View File

@@ -8,9 +8,11 @@ using Android.App;
using Android.App.Assist;
using Android.Content;
using Android.Content.PM;
using Android.Hardware.Biometrics;
using Android.Nfc;
using Android.OS;
using Android.Provider;
using Android.Runtime;
using Android.Support.V4.App;
using Android.Support.V4.Content;
using Android.Text;
@@ -28,6 +30,7 @@ using Bit.Core.Models.View;
using Bit.Core.Utilities;
using Bit.Droid.Autofill;
using Plugin.CurrentActivity;
using Plugin.Fingerprint;
namespace Bit.Droid.Services
{
@@ -335,11 +338,72 @@ namespace Bit.Droid.Services
Application.Context.PackageName, 0).VersionCode.ToString();
}
public bool SupportsFaceId()
public bool SupportsFaceBiometric()
{
return false;
}
public Task<bool> SupportsFaceBiometricAsync()
{
return Task.FromResult(SupportsFaceBiometric());
}
public async Task<bool> BiometricAvailableAsync()
{
if(UseNativeBiometric())
{
var activity = (MainActivity)CrossCurrentActivity.Current.Activity;
var manager = activity.GetSystemService(Context.BiometricService) as BiometricManager;
return manager.CanAuthenticate() == BiometricCode.Success;
}
else
{
try
{
return await CrossFingerprint.Current.IsAvailableAsync();
}
catch
{
return false;
}
}
}
public bool UseNativeBiometric()
{
return (int)Build.VERSION.SdkInt >= 28;
}
public Task<bool> AuthenticateBiometricAsync(string text = null)
{
if(string.IsNullOrWhiteSpace(text))
{
text = AppResources.BiometricDirection;
}
var activity = (MainActivity)CrossCurrentActivity.Current.Activity;
using(var builder = new BiometricPrompt.Builder(activity))
{
builder.SetTitle(text);
builder.SetConfirmationRequired(false);
builder.SetNegativeButton(AppResources.Cancel, activity.MainExecutor,
new DialogInterfaceOnClickListener
{
Clicked = () => { }
});
var prompt = builder.Build();
var result = new TaskCompletionSource<bool>();
prompt.Authenticate(new CancellationSignal(), activity.MainExecutor,
new BiometricAuthenticationCallback
{
Success = authResult => result.TrySetResult(true),
Failed = () => result.TrySetResult(false),
Help = (helpCode, helpString) => { }
});
return result.Task;
}
}
public bool SupportsNfc()
{
var activity = (MainActivity)CrossCurrentActivity.Current.Activity;
@@ -715,5 +779,41 @@ namespace Bit.Droid.Services
Context.ClipboardService) as Android.Content.ClipboardManager;
clipboardManager.Text = text;
}
private class BiometricAuthenticationCallback : BiometricPrompt.AuthenticationCallback
{
public Action<BiometricPrompt.AuthenticationResult> Success { get; set; }
public Action Failed { get; set; }
public Action<BiometricAcquiredStatus, Java.Lang.ICharSequence> Help { get; set; }
public override void OnAuthenticationSucceeded(BiometricPrompt.AuthenticationResult authResult)
{
base.OnAuthenticationSucceeded(authResult);
Success?.Invoke(authResult);
}
public override void OnAuthenticationFailed()
{
base.OnAuthenticationFailed();
Failed?.Invoke();
}
public override void OnAuthenticationHelp([GeneratedEnum] BiometricAcquiredStatus helpCode,
Java.Lang.ICharSequence helpString)
{
base.OnAuthenticationHelp(helpCode, helpString);
Help?.Invoke(helpCode, helpString);
}
}
private class DialogInterfaceOnClickListener : Java.Lang.Object, IDialogInterfaceOnClickListener
{
public Action Clicked { get; set; }
public void OnClick(IDialogInterface dialog, int which)
{
Clicked?.Invoke();
}
}
}
}