fingerprint setup

This commit is contained in:
Kyle Spearrin 2019-05-16 16:31:58 -04:00
parent 6e42f5ce7b
commit 22a0b262e1
7 changed files with 581 additions and 481 deletions

View file

@ -9,6 +9,9 @@ using Bit.Core.Abstractions;
using Bit.Core.Services; using Bit.Core.Services;
using Bit.Core.Utilities; using Bit.Core.Utilities;
using Bit.Droid.Services; using Bit.Droid.Services;
using Plugin.CurrentActivity;
using Plugin.Fingerprint;
using Plugin.Fingerprint.Abstractions;
namespace Bit.Droid namespace Bit.Droid
{ {
@ -34,14 +37,16 @@ namespace Bit.Droid
{ {
base.OnCreate(); base.OnCreate();
Bootstrap(); Bootstrap();
Plugin.CurrentActivity.CrossCurrentActivity.Current.Init(this); CrossCurrentActivity.Current.Init(this);
} }
private void RegisterLocalServices() private void RegisterLocalServices()
{ {
// CrossFingerprint.SetCurrentActivityResolver(() => CrossCurrentActivity.Current.Activity);
Refractored.FabControl.Droid.FloatingActionButtonViewRenderer.Init(); Refractored.FabControl.Droid.FloatingActionButtonViewRenderer.Init();
// Note: This might cause a race condition. Investigate more. // Note: This might cause a race condition. Investigate more.
Task.Run(() => FFImageLoading.Forms.Platform.CachedImageRenderer.Init(true)); Task.Run(() => FFImageLoading.Forms.Platform.CachedImageRenderer.Init(true));
CrossFingerprint.SetCurrentActivityResolver(() => CrossCurrentActivity.Current.Activity);
var preferencesStorage = new PreferencesStorageService(null); var preferencesStorage = new PreferencesStorageService(null);
var documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal); var documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);

File diff suppressed because it is too large Load diff

View file

@ -12,6 +12,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Plugin.Fingerprint" Version="1.4.9" />
<PackageReference Include="Refractored.FloatingActionButtonForms" Version="2.1.0" /> <PackageReference Include="Refractored.FloatingActionButtonForms" Version="2.1.0" />
<PackageReference Include="Xamarin.Essentials" Version="1.1.0" /> <PackageReference Include="Xamarin.Essentials" Version="1.1.0" />
<PackageReference Include="Xamarin.FFImageLoading.Forms" Version="2.4.9.961" /> <PackageReference Include="Xamarin.FFImageLoading.Forms" Version="2.4.9.961" />

View file

@ -23,6 +23,8 @@ namespace Bit.App.Pages
private readonly IStorageService _storageService; private readonly IStorageService _storageService;
private readonly ISyncService _syncService; private readonly ISyncService _syncService;
private string _fingerprintName;
private bool _supportsFingerprint;
private bool _pin; private bool _pin;
private bool _fingerprint; private bool _fingerprint;
private string _lastSyncDate; private string _lastSyncDate;
@ -54,12 +56,20 @@ namespace Bit.App.Pages
GroupedItems = new ExtendedObservableCollection<SettingsPageListGroup>(); GroupedItems = new ExtendedObservableCollection<SettingsPageListGroup>();
PageTitle = AppResources.Settings; PageTitle = AppResources.Settings;
_fingerprintName = AppResources.Fingerprint;
if(Device.RuntimePlatform == Device.iOS)
{
_fingerprintName = AppResources.TouchID;
// TODO: face id
}
} }
public ExtendedObservableCollection<SettingsPageListGroup> GroupedItems { get; set; } public ExtendedObservableCollection<SettingsPageListGroup> GroupedItems { get; set; }
public async Task InitAsync() public async Task InitAsync()
{ {
_supportsFingerprint = await _platformUtilsService.SupportsFingerprintAsync();
var lastSync = await _syncService.GetLastSyncAsync(); var lastSync = await _syncService.GetLastSyncAsync();
if(lastSync != null) if(lastSync != null)
{ {
@ -228,7 +238,7 @@ namespace Bit.App.Pages
await _storageService.RemoveAsync(Constants.PinProtectedKey); await _storageService.RemoveAsync(Constants.PinProtectedKey);
await _storageService.RemoveAsync(Constants.ProtectedPin); await _storageService.RemoveAsync(Constants.ProtectedPin);
} }
BuildList(); BuildList();
} }
@ -243,11 +253,19 @@ namespace Bit.App.Pages
var securityItems = new List<SettingsPageListItem> var securityItems = new List<SettingsPageListItem>
{ {
new SettingsPageListItem { Name = AppResources.LockOptions, SubLabel = _lockOptionValue }, new SettingsPageListItem { Name = AppResources.LockOptions, SubLabel = _lockOptionValue },
new SettingsPageListItem { Name = string.Format(AppResources.UnlockWith, AppResources.Fingerprint) },
new SettingsPageListItem { Name = AppResources.UnlockWithPIN, SubLabel = _pin ? "✓" : null }, new SettingsPageListItem { Name = AppResources.UnlockWithPIN, SubLabel = _pin ? "✓" : null },
new SettingsPageListItem { Name = AppResources.LockNow }, new SettingsPageListItem { Name = AppResources.LockNow },
new SettingsPageListItem { Name = AppResources.TwoStepLogin } new SettingsPageListItem { Name = AppResources.TwoStepLogin }
}; };
if(_supportsFingerprint)
{
var item = new SettingsPageListItem
{
Name = string.Format(AppResources.UnlockWith, _fingerprintName),
SubLabel = _fingerprint ? "✓" : null
};
securityItems.Insert(1, item);
}
var accountItems = new List<SettingsPageListItem> var accountItems = new List<SettingsPageListItem>
{ {
new SettingsPageListItem { Name = AppResources.ChangeMasterPassword }, new SettingsPageListItem { Name = AppResources.ChangeMasterPassword },

View file

@ -1,6 +1,9 @@
using Bit.App.Abstractions; using Bit.App.Abstractions;
using Bit.App.Models; using Bit.App.Models;
using Bit.App.Resources;
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using Plugin.Fingerprint;
using Plugin.Fingerprint.Abstractions;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -184,5 +187,45 @@ namespace Bit.App.Services
{ {
return await Clipboard.GetTextAsync(); return await Clipboard.GetTextAsync();
} }
public async Task<bool> SupportsFingerprintAsync()
{
try
{
return await CrossFingerprint.Current.IsAvailableAsync();
}
catch
{
return false;
}
}
public async Task<bool> AuthenticateFingerprintAsync(string text = null, Action fallback = null)
{
try
{
if(text == null)
{
text = AppResources.FingerprintDirection;
}
var fingerprintRequest = new AuthenticationRequestConfiguration(text)
{
AllowAlternativeAuthentication = true,
CancelTitle = AppResources.Cancel,
FallbackTitle = AppResources.LogOut
};
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

@ -1,4 +1,5 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Bit.Core.Enums; using Bit.Core.Enums;
@ -25,5 +26,7 @@ namespace Bit.Core.Abstractions
void ShowToast(string type, string title, string[] text, Dictionary<string, object> options = null); void ShowToast(string type, string title, string[] text, Dictionary<string, object> options = null);
bool SupportsU2f(); bool SupportsU2f();
bool SupportsDuo(); bool SupportsDuo();
Task<bool> SupportsFingerprintAsync();
Task<bool> AuthenticateFingerprintAsync(string text = null, Action fallback = null);
} }
} }

View file

@ -41,5 +41,7 @@
<string>FontAwesome.ttf</string> <string>FontAwesome.ttf</string>
<string>MaterialIcons_Regular.ttf</string> <string>MaterialIcons_Regular.ttf</string>
</array> </array>
<key>NSFaceIDUsageDescription</key>
<string>Use Face ID to unlock your vault.</string>
</dict> </dict>
</plist> </plist>