security settings for touch id and locking
This commit is contained in:
parent
c408614a85
commit
29236f7462
@ -70,10 +70,48 @@ namespace Bit.App
|
|||||||
|
|
||||||
private async Task CheckLockAsync()
|
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)
|
||||||
|
{
|
||||||
|
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);
|
await Current.MainPage.Navigation.PushModalAsync(new LockFingerprintPage(), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(pinUnlock)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Use master password to unlock if no other methods are set
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
<Compile Include="Behaviors\EmailValidationBehavior.cs" />
|
<Compile Include="Behaviors\EmailValidationBehavior.cs" />
|
||||||
<Compile Include="Behaviors\ConnectivityBehavior.cs" />
|
<Compile Include="Behaviors\ConnectivityBehavior.cs" />
|
||||||
<Compile Include="Behaviors\RequiredValidationBehavior.cs" />
|
<Compile Include="Behaviors\RequiredValidationBehavior.cs" />
|
||||||
|
<Compile Include="Constants.cs" />
|
||||||
<Compile Include="Controls\DismissModalToolBarItem.cs" />
|
<Compile Include="Controls\DismissModalToolBarItem.cs" />
|
||||||
<Compile Include="Controls\EntryLabel.cs" />
|
<Compile Include="Controls\EntryLabel.cs" />
|
||||||
<Compile Include="Controls\ExtendedEditor.cs" />
|
<Compile Include="Controls\ExtendedEditor.cs" />
|
||||||
@ -220,6 +221,9 @@
|
|||||||
<LastGenOutput>AppResources.Designer.cs</LastGenOutput>
|
<LastGenOutput>AppResources.Designer.cs</LastGenOutput>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Enums\" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
|
<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')" />
|
<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">
|
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||||
|
10
src/App/Constants.cs
Normal file
10
src/App/Constants.cs
Normal 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";
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,8 @@ using Xamarin.Forms;
|
|||||||
using XLabs.Ioc;
|
using XLabs.Ioc;
|
||||||
using Bit.App.Controls;
|
using Bit.App.Controls;
|
||||||
using Acr.UserDialogs;
|
using Acr.UserDialogs;
|
||||||
|
using Plugin.Settings.Abstractions;
|
||||||
|
using Plugin.Fingerprint.Abstractions;
|
||||||
|
|
||||||
namespace Bit.App.Pages
|
namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
@ -12,28 +14,50 @@ namespace Bit.App.Pages
|
|||||||
{
|
{
|
||||||
private readonly IAuthService _authService;
|
private readonly IAuthService _authService;
|
||||||
private readonly IUserDialogs _userDialogs;
|
private readonly IUserDialogs _userDialogs;
|
||||||
|
private readonly ISettings _settings;
|
||||||
|
private readonly IFingerprint _fingerprint;
|
||||||
|
|
||||||
|
// TODO: Model binding context?
|
||||||
|
|
||||||
public SettingsPage()
|
public SettingsPage()
|
||||||
{
|
{
|
||||||
_authService = Resolver.Resolve<IAuthService>();
|
_authService = Resolver.Resolve<IAuthService>();
|
||||||
_userDialogs = Resolver.Resolve<IUserDialogs>();
|
_userDialogs = Resolver.Resolve<IUserDialogs>();
|
||||||
|
_settings = Resolver.Resolve<ISettings>();
|
||||||
|
_fingerprint = Resolver.Resolve<IFingerprint>();
|
||||||
|
|
||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ExtendedSwitchCell PinCell { get; set; }
|
||||||
|
private ExtendedSwitchCell FingerprintCell { get; set; }
|
||||||
|
private ExtendedTextCell LockOptionsCell { get; set; }
|
||||||
|
|
||||||
private void Init()
|
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
|
var changeMasterPasswordCell = new ExtendedTextCell
|
||||||
{
|
{
|
||||||
@ -72,8 +96,9 @@ namespace Bit.App.Pages
|
|||||||
{
|
{
|
||||||
new TableSection("Security")
|
new TableSection("Security")
|
||||||
{
|
{
|
||||||
touchIdCell,
|
LockOptionsCell,
|
||||||
lockOnExitCell,
|
FingerprintCell,
|
||||||
|
PinCell,
|
||||||
changeMasterPasswordCell
|
changeMasterPasswordCell
|
||||||
},
|
},
|
||||||
new TableSection("Manage Folders")
|
new TableSection("Manage Folders")
|
||||||
@ -97,6 +122,29 @@ namespace Bit.App.Pages
|
|||||||
Content = table;
|
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)
|
private void LockCell_Tapped(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -113,11 +161,6 @@ namespace Bit.App.Pages
|
|||||||
Application.Current.MainPage = new LoginNavigationPage();
|
Application.Current.MainPage = new LoginNavigationPage();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LockOnExitCell_Changed(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void ChangeMasterPasswordCell_Tapped(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))
|
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"));
|
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)
|
private void FoldersCell_Tapped(object sender, EventArgs e)
|
||||||
|
@ -19,6 +19,7 @@ using Plugin.Fingerprint.Abstractions;
|
|||||||
using Plugin.Settings.Abstractions;
|
using Plugin.Settings.Abstractions;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
|
using Bit.App;
|
||||||
|
|
||||||
namespace Bit.iOS
|
namespace Bit.iOS
|
||||||
{
|
{
|
||||||
@ -61,13 +62,17 @@ namespace Bit.iOS
|
|||||||
|
|
||||||
public override void DidEnterBackground(UIApplication uiApplication)
|
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,
|
BackgroundColor = UIColor.Black,
|
||||||
Tag = 4321
|
Tag = 4321
|
||||||
};
|
};
|
||||||
UIApplication.SharedApplication.KeyWindow.AddSubview(colourView);
|
UIApplication.SharedApplication.KeyWindow.AddSubview(colorView);
|
||||||
UIApplication.SharedApplication.KeyWindow.BringSubviewToFront(colourView);
|
UIApplication.SharedApplication.KeyWindow.BringSubviewToFront(colorView);
|
||||||
|
|
||||||
|
// Log the date/time we last backgrounded
|
||||||
|
CrossSettings.Current.AddOrUpdateValue(Constants.SettingLastBackgroundedDate, DateTime.UtcNow);
|
||||||
|
|
||||||
base.DidEnterBackground(uiApplication);
|
base.DidEnterBackground(uiApplication);
|
||||||
Debug.WriteLine("DidEnterBackground");
|
Debug.WriteLine("DidEnterBackground");
|
||||||
@ -107,7 +112,7 @@ namespace Bit.iOS
|
|||||||
|
|
||||||
private void SendLockMessage()
|
private void SendLockMessage()
|
||||||
{
|
{
|
||||||
MessagingCenter.Send<App.App>(_app, "Lock");
|
MessagingCenter.Send(_app, "Lock");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user