From bf4f0bdba03b853af3148511c1fadab4cc20bf04 Mon Sep 17 00:00:00 2001 From: Kyle Spearrin Date: Mon, 27 May 2019 11:57:10 -0400 Subject: [PATCH] two-factor page UI --- src/App/Pages/Accounts/LoginPageViewModel.cs | 3 +- src/App/Pages/Accounts/TwoFactorPage.xaml | 92 ++++++++++++++++++- src/App/Pages/Accounts/TwoFactorPage.xaml.cs | 6 +- .../Pages/Accounts/TwoFactorPageViewModel.cs | 39 +++++++- 4 files changed, 131 insertions(+), 9 deletions(-) diff --git a/src/App/Pages/Accounts/LoginPageViewModel.cs b/src/App/Pages/Accounts/LoginPageViewModel.cs index 34c58541c..7025cb26c 100644 --- a/src/App/Pages/Accounts/LoginPageViewModel.cs +++ b/src/App/Pages/Accounts/LoginPageViewModel.cs @@ -100,7 +100,8 @@ namespace Bit.App.Pages } if(response.TwoFactor) { - // TODO: 2fa page + var page = new TwoFactorPage(); + await Page.Navigation.PushModalAsync(new NavigationPage(page)); } else { diff --git a/src/App/Pages/Accounts/TwoFactorPage.xaml b/src/App/Pages/Accounts/TwoFactorPage.xaml index e9b5cd6e0..76526237e 100644 --- a/src/App/Pages/Accounts/TwoFactorPage.xaml +++ b/src/App/Pages/Accounts/TwoFactorPage.xaml @@ -16,15 +16,103 @@ + - + - + + + + + + + + + + + + + + + + diff --git a/src/App/Pages/Accounts/TwoFactorPage.xaml.cs b/src/App/Pages/Accounts/TwoFactorPage.xaml.cs index ba2a82d1c..c37ef6592 100644 --- a/src/App/Pages/Accounts/TwoFactorPage.xaml.cs +++ b/src/App/Pages/Accounts/TwoFactorPage.xaml.cs @@ -1,4 +1,5 @@ -using System; +using Bit.App.Controls; +using System; namespace Bit.App.Pages { @@ -11,8 +12,11 @@ namespace Bit.App.Pages InitializeComponent(); _vm = BindingContext as TwoFactorPageViewModel; _vm.Page = this; + DuoWebView = _duoWebView; } + public HybridWebView DuoWebView { get; set; } + protected override void OnAppearing() { base.OnAppearing(); diff --git a/src/App/Pages/Accounts/TwoFactorPageViewModel.cs b/src/App/Pages/Accounts/TwoFactorPageViewModel.cs index 14497d4a2..dfda85041 100644 --- a/src/App/Pages/Accounts/TwoFactorPageViewModel.cs +++ b/src/App/Pages/Accounts/TwoFactorPageViewModel.cs @@ -6,6 +6,7 @@ using Bit.Core.Exceptions; using Bit.Core.Models.Request; using Bit.Core.Utilities; using System.Linq; +using System.Net; using System.Threading.Tasks; using Xamarin.Forms; @@ -19,10 +20,12 @@ namespace Bit.App.Pages private readonly IStorageService _storageService; private readonly IApiService _apiService; private readonly IPlatformUtilsService _platformUtilsService; + private readonly IEnvironmentService _environmentService; private bool _u2fSupported = false; private TwoFactorProviderType? _selectedProviderType; private string _twoFactorEmail; + private string _webVaultUrl = "https://vault.bitwarden.com"; public TwoFactorPageViewModel() { @@ -32,6 +35,7 @@ namespace Bit.App.Pages _storageService = ServiceContainer.Resolve("storageService"); _apiService = ServiceContainer.Resolve("apiService"); _platformUtilsService = ServiceContainer.Resolve("platformUtilsService"); + _environmentService = ServiceContainer.Resolve("environmentService"); } public string TwoFactorEmail @@ -52,6 +56,14 @@ namespace Bit.App.Pages public bool EmailMethod => SelectedProviderType == TwoFactorProviderType.Email; + public bool TotpMethod => AuthenticatorMethod || EmailMethod; + + public string TotpInstruction => AuthenticatorMethod ? AppResources.EnterVerificationCodeApp : + AppResources.EnterVerificationCodeEmail; + + public string YubikeyInstruction => Device.RuntimePlatform == Device.iOS ? AppResources.YubiKeyInstructionIos : + AppResources.YubiKeyInstruction; + public TwoFactorProviderType? SelectedProviderType { get => _selectedProviderType; @@ -60,7 +72,9 @@ namespace Bit.App.Pages nameof(EmailMethod), nameof(DuoMethod), nameof(YubikeyMethod), - nameof(AuthenticatorMethod) + nameof(AuthenticatorMethod), + nameof(TotpMethod), + nameof(TotpInstruction) }); } @@ -74,10 +88,19 @@ namespace Bit.App.Pages return; } + if(!string.IsNullOrWhiteSpace(_environmentService.BaseUrl)) + { + _webVaultUrl = _environmentService.BaseUrl; + } + else if(!string.IsNullOrWhiteSpace(_environmentService.WebVaultUrl)) + { + _webVaultUrl = _environmentService.WebVaultUrl; + } + // TODO: init U2F _u2fSupported = false; - var selectedProviderType = _authService.GetDefaultTwoFactorProvider(_u2fSupported); + SelectedProviderType = _authService.GetDefaultTwoFactorProvider(_u2fSupported); Load(); } @@ -97,9 +120,15 @@ namespace Bit.App.Pages break; case TwoFactorProviderType.Duo: case TwoFactorProviderType.OrganizationDuo: - // TODO: init duo - var host = providerData["Host"] as string; - var signature = providerData["Signature"] as string; + var host = WebUtility.UrlEncode(providerData["Host"] as string); + var req = WebUtility.UrlEncode(providerData["Signature"] as string); + var page = Page as TwoFactorPage; + page.DuoWebView.Uri = $"{_webVaultUrl}/duo-connector.html?host={host}&request={req}"; + page.DuoWebView.RegisterAction(async sig => + { + Token = sig; + await SubmitAsync(); + }); break; case TwoFactorProviderType.Email: TwoFactorEmail = providerData["Email"] as string;