From 29236f7462c5ceb168c9dd49967aeb8c18484606 Mon Sep 17 00:00:00 2001 From: Kyle Spearrin Date: Sat, 21 May 2016 22:50:15 -0400 Subject: [PATCH] security settings for touch id and locking --- src/App/App.cs | 42 +++++++++++++- src/App/App.csproj | 4 ++ src/App/Constants.cs | 10 ++++ src/App/Pages/SettingsPage.cs | 101 +++++++++++++++++++++++++++++----- src/iOS/AppDelegate.cs | 13 +++-- 5 files changed, 149 insertions(+), 21 deletions(-) create mode 100644 src/App/Constants.cs diff --git a/src/App/App.cs b/src/App/App.cs index 30a7c176a..bc6b75478 100644 --- a/src/App/App.cs +++ b/src/App/App.cs @@ -70,9 +70,47 @@ namespace Bit.App private async Task CheckLockAsync() { - if(_authService.IsAuthenticated && Current.MainPage.Navigation.ModalStack.LastOrDefault() as LockFingerprintPage == null) + // Only lock if they are logged in + if(!_authService.IsAuthenticated) { - await Current.MainPage.Navigation.PushModalAsync(new LockFingerprintPage(), false); + return; + } + + // Lock seconds tells if if they want to lock the app or not + var lockSeconds = _settings.GetValueOrDefault(Constants.SettingLockSeconds); + if(!lockSeconds.HasValue) + { + return; + } + + // Has it been longer than lockSeconds since the last time the app was backgrounded? + var now = DateTime.UtcNow; + var lastBackground = _settings.GetValueOrDefault(Constants.SettingLastBackgroundedDate, now.AddYears(-1)); + if((now - lastBackground).TotalSeconds < lockSeconds.Value) + { + return; + } + + // What method are we using to unlock? + var fingerprintUnlock = _settings.GetValueOrDefault(Constants.SettingFingerprintUnlockOn); + var pinUnlock = _settings.GetValueOrDefault(Constants.SettingPinUnlockOn); + if(fingerprintUnlock && _fingerprint.IsAvailable) + { + if(Device.OS == TargetPlatform.iOS) + { + if(Current.MainPage.Navigation.ModalStack.LastOrDefault() as LockFingerprintPage == null) + { + await Current.MainPage.Navigation.PushModalAsync(new LockFingerprintPage(), false); + } + } + } + else if(pinUnlock) + { + + } + else + { + // Use master password to unlock if no other methods are set } } } diff --git a/src/App/App.csproj b/src/App/App.csproj index 129542958..b4624b49d 100644 --- a/src/App/App.csproj +++ b/src/App/App.csproj @@ -44,6 +44,7 @@ + @@ -220,6 +221,9 @@ AppResources.Designer.cs + + + diff --git a/src/App/Constants.cs b/src/App/Constants.cs new file mode 100644 index 000000000..98876f2da --- /dev/null +++ b/src/App/Constants.cs @@ -0,0 +1,10 @@ +namespace Bit.App +{ + public static class Constants + { + public const string SettingFingerprintUnlockOn = "fingerprintUnlockOn"; + public const string SettingPinUnlockOn = "pinUnlockOn"; + public const string SettingLockSeconds = "lockSeconds"; + public const string SettingLastBackgroundedDate = "lastBackgroundedDate"; + } +} diff --git a/src/App/Pages/SettingsPage.cs b/src/App/Pages/SettingsPage.cs index ce64de6bd..25185bba4 100644 --- a/src/App/Pages/SettingsPage.cs +++ b/src/App/Pages/SettingsPage.cs @@ -5,6 +5,8 @@ using Xamarin.Forms; using XLabs.Ioc; using Bit.App.Controls; using Acr.UserDialogs; +using Plugin.Settings.Abstractions; +using Plugin.Fingerprint.Abstractions; namespace Bit.App.Pages { @@ -12,28 +14,50 @@ namespace Bit.App.Pages { private readonly IAuthService _authService; private readonly IUserDialogs _userDialogs; + private readonly ISettings _settings; + private readonly IFingerprint _fingerprint; + + // TODO: Model binding context? public SettingsPage() { _authService = Resolver.Resolve(); _userDialogs = Resolver.Resolve(); + _settings = Resolver.Resolve(); + _fingerprint = Resolver.Resolve(); Init(); } + private ExtendedSwitchCell PinCell { get; set; } + private ExtendedSwitchCell FingerprintCell { get; set; } + private ExtendedTextCell LockOptionsCell { get; set; } + private void Init() { - var touchIdCell = new ExtendedSwitchCell + FingerprintCell = new ExtendedSwitchCell { - Text = "Use Touch ID" + Text = "Use Touch ID" + (!_fingerprint.IsAvailable ? " (Unavilable)" : null), + On = _settings.GetValueOrDefault(Constants.SettingFingerprintUnlockOn), + IsEnabled = _fingerprint.IsAvailable }; - touchIdCell.OnChanged += TouchIdCell_Changed; + FingerprintCell.OnChanged += FingerprintCell_Changed; - var lockOnExitCell = new ExtendedSwitchCell + PinCell = new ExtendedSwitchCell { - Text = "Lock Immediately On Exit" + Text = "Use PIN Code", + On = _settings.GetValueOrDefault(Constants.SettingPinUnlockOn) }; - lockOnExitCell.OnChanged += LockOnExitCell_Changed; + PinCell.OnChanged += PinCell_Changed; + + LockOptionsCell = new ExtendedTextCell + { + Text = "Lock Options", + // TODO: Set detail based on setting + Detail = "Immediately", + ShowDisclousure = true + }; + LockOptionsCell.Tapped += LockOptionsCell_Tapped; var changeMasterPasswordCell = new ExtendedTextCell { @@ -72,8 +96,9 @@ namespace Bit.App.Pages { new TableSection("Security") { - touchIdCell, - lockOnExitCell, + LockOptionsCell, + FingerprintCell, + PinCell, changeMasterPasswordCell }, new TableSection("Manage Folders") @@ -97,6 +122,29 @@ namespace Bit.App.Pages Content = table; } + private async void LockOptionsCell_Tapped(object sender, EventArgs e) + { + var selection = await DisplayActionSheet("Lock Options", AppResources.Cancel, null, + "Immediately", "1 minute", "3 minutes", "15 minutes", "1 hour", "8 hours", "24 hours", "Never"); + + if(selection == "Immediately") + { + _settings.AddOrUpdateValue(Constants.SettingLockSeconds, 0); + } + else if(selection == "1 minute") + { + _settings.AddOrUpdateValue(Constants.SettingLockSeconds, 60); + } + // TODO: others + else + { + // Never lock + _settings.Remove(Constants.SettingLockSeconds); + } + + LockOptionsCell.Detail = selection; + } + private void LockCell_Tapped(object sender, EventArgs e) { @@ -113,11 +161,6 @@ namespace Bit.App.Pages Application.Current.MainPage = new LoginNavigationPage(); } - private void LockOnExitCell_Changed(object sender, EventArgs e) - { - - } - private async void ChangeMasterPasswordCell_Tapped(object sender, EventArgs e) { if(!await _userDialogs.ConfirmAsync("You can change your master password on the bitwarden.com web vault. Do you want to visit the website now?", null, AppResources.Yes, AppResources.Cancel)) @@ -128,9 +171,37 @@ namespace Bit.App.Pages Device.OpenUri(new Uri("https://vault.bitwarden.com")); } - private void TouchIdCell_Changed(object sender, EventArgs e) + private void FingerprintCell_Changed(object sender, EventArgs e) { - + var cell = sender as ExtendedSwitchCell; + if(cell == null) + { + return; + } + + _settings.AddOrUpdateValue(Constants.SettingFingerprintUnlockOn, cell.On); + + if(cell.On) + { + _settings.AddOrUpdateValue(Constants.SettingPinUnlockOn, false); + PinCell.On = false; + } + } + + private void PinCell_Changed(object sender, EventArgs e) + { + var cell = sender as ExtendedSwitchCell; + if(cell == null) + { + return; + } + + _settings.AddOrUpdateValue(Constants.SettingPinUnlockOn, cell.On); + if(cell.On) + { + _settings.AddOrUpdateValue(Constants.SettingFingerprintUnlockOn, false); + FingerprintCell.On = false; + } } private void FoldersCell_Tapped(object sender, EventArgs e) diff --git a/src/iOS/AppDelegate.cs b/src/iOS/AppDelegate.cs index bfbe05950..3d4e8c6cc 100644 --- a/src/iOS/AppDelegate.cs +++ b/src/iOS/AppDelegate.cs @@ -19,6 +19,7 @@ using Plugin.Fingerprint.Abstractions; using Plugin.Settings.Abstractions; using System.Diagnostics; using Xamarin.Forms; +using Bit.App; namespace Bit.iOS { @@ -61,13 +62,17 @@ namespace Bit.iOS public override void DidEnterBackground(UIApplication uiApplication) { - var colourView = new UIView(UIApplication.SharedApplication.KeyWindow.Frame) + // TODO: Make this an image view + var colorView = new UIView(UIApplication.SharedApplication.KeyWindow.Frame) { BackgroundColor = UIColor.Black, Tag = 4321 }; - UIApplication.SharedApplication.KeyWindow.AddSubview(colourView); - UIApplication.SharedApplication.KeyWindow.BringSubviewToFront(colourView); + UIApplication.SharedApplication.KeyWindow.AddSubview(colorView); + UIApplication.SharedApplication.KeyWindow.BringSubviewToFront(colorView); + + // Log the date/time we last backgrounded + CrossSettings.Current.AddOrUpdateValue(Constants.SettingLastBackgroundedDate, DateTime.UtcNow); base.DidEnterBackground(uiApplication); Debug.WriteLine("DidEnterBackground"); @@ -107,7 +112,7 @@ namespace Bit.iOS private void SendLockMessage() { - MessagingCenter.Send(_app, "Lock"); + MessagingCenter.Send(_app, "Lock"); }