security settings for touch id and locking

This commit is contained in:
Kyle Spearrin 2016-05-21 22:50:15 -04:00
parent c408614a85
commit 29236f7462
5 changed files with 149 additions and 21 deletions

View File

@ -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<int?>(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<bool>(Constants.SettingFingerprintUnlockOn);
var pinUnlock = _settings.GetValueOrDefault<bool>(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
}
}
}

View File

@ -44,6 +44,7 @@
<Compile Include="Behaviors\EmailValidationBehavior.cs" />
<Compile Include="Behaviors\ConnectivityBehavior.cs" />
<Compile Include="Behaviors\RequiredValidationBehavior.cs" />
<Compile Include="Constants.cs" />
<Compile Include="Controls\DismissModalToolBarItem.cs" />
<Compile Include="Controls\EntryLabel.cs" />
<Compile Include="Controls\ExtendedEditor.cs" />
@ -220,6 +221,9 @@
<LastGenOutput>AppResources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Folder Include="Enums\" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
<Import Project="..\..\packages\Xamarin.Forms.2.2.0.31\build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Xamarin.Forms.targets" Condition="Exists('..\..\packages\Xamarin.Forms.2.2.0.31\build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Xamarin.Forms.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">

10
src/App/Constants.cs Normal file
View File

@ -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";
}
}

View File

@ -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<IAuthService>();
_userDialogs = Resolver.Resolve<IUserDialogs>();
_settings = Resolver.Resolve<ISettings>();
_fingerprint = Resolver.Resolve<IFingerprint>();
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<bool>(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<bool>(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)

View File

@ -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.App>(_app, "Lock");
MessagingCenter.Send(_app, "Lock");
}