mirror of
https://github.com/bitwarden/android.git
synced 2024-12-25 02:18:27 +03:00
two-factor page UI
This commit is contained in:
parent
e8705d49f2
commit
bf4f0bdba0
4 changed files with 131 additions and 9 deletions
|
@ -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
|
||||
{
|
||||
|
|
|
@ -16,15 +16,103 @@
|
|||
<ContentPage.Resources>
|
||||
<ResourceDictionary>
|
||||
<u:InverseBoolConverter x:Key="inverseBool" />
|
||||
<u:IsNullConverter x:Key="isNull" />
|
||||
</ResourceDictionary>
|
||||
</ContentPage.Resources>
|
||||
|
||||
<ContentPage.ToolbarItems>
|
||||
<ToolbarItem Text="{u:I18n Continue}" Clicked="Continue_Clicked" />
|
||||
<ToolbarItem Text="{u:I18n Continue}" Clicked="Continue_Clicked" x:Name="_continueItem" />
|
||||
</ContentPage.ToolbarItems>
|
||||
|
||||
<ScrollView>
|
||||
|
||||
<StackLayout Spacing="0" Padding="0">
|
||||
<StackLayout Spacing="0" Padding="0" IsVisible="{Binding TotpMethod, Mode=OneWay}">
|
||||
<Label
|
||||
Text="{Binding TotpInstruction, Mode=OneWay}"
|
||||
Margin="20, 0"
|
||||
HorizontalTextAlignment="Center" />
|
||||
<StackLayout StyleClass="box">
|
||||
<StackLayout StyleClass="box-row, box-row-input">
|
||||
<Label
|
||||
Text="{u:I18n VerificationCode}"
|
||||
StyleClass="box-label" />
|
||||
<Entry
|
||||
Text="{Binding Token}"
|
||||
Keyboard="Numeric"
|
||||
StyleClass="box-value" />
|
||||
</StackLayout>
|
||||
<StackLayout StyleClass="box-row, box-row-switch">
|
||||
<Label
|
||||
Text="{u:I18n RememberMe}"
|
||||
StyleClass="box-label, box-label-regular"
|
||||
HorizontalOptions="StartAndExpand" />
|
||||
<Switch
|
||||
IsToggled="{Binding Remember}"
|
||||
StyleClass="box-value"
|
||||
HorizontalOptions="End" />
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
<StackLayout Spacing="0" Padding="0" IsVisible="{Binding YubikeyMethod, Mode=OneWay}">
|
||||
<Label
|
||||
Text="{Binding YubikeyInstruction, Mode=OneWay}"
|
||||
Margin="20, 0"
|
||||
HorizontalTextAlignment="Center" />
|
||||
<Image
|
||||
Source="yubikey.png"
|
||||
Margin="20, 0"
|
||||
WidthRequest="266"
|
||||
HeightRequest="160"
|
||||
HorizontalOptions="Center" />
|
||||
<StackLayout StyleClass="box">
|
||||
<StackLayout StyleClass="box-row, box-row-input">
|
||||
<Entry
|
||||
Text="{Binding Token}"
|
||||
StyleClass="box-value" />
|
||||
</StackLayout>
|
||||
<StackLayout StyleClass="box-row, box-row-switch">
|
||||
<Label
|
||||
Text="{u:I18n RememberMe}"
|
||||
StyleClass="box-label, box-label-regular"
|
||||
HorizontalOptions="StartAndExpand" />
|
||||
<Switch
|
||||
IsToggled="{Binding Remember}"
|
||||
StyleClass="box-value"
|
||||
HorizontalOptions="End" />
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
<StackLayout Spacing="0" Padding="0" IsVisible="{Binding DuoMethod, Mode=OneWay}">
|
||||
<controls:HybridWebView
|
||||
x:Name="_duoWebView"
|
||||
HorizontalOptions="FillAndExpand"
|
||||
VerticalOptions="FillAndExpand"
|
||||
MinimumHeightRequest="400" />
|
||||
<StackLayout StyleClass="box">
|
||||
<StackLayout StyleClass="box-row, box-row-switch">
|
||||
<Label
|
||||
Text="{u:I18n RememberMe}"
|
||||
StyleClass="box-label, box-label-regular"
|
||||
HorizontalOptions="StartAndExpand" />
|
||||
<Switch
|
||||
IsToggled="{Binding Remember}"
|
||||
StyleClass="box-value"
|
||||
HorizontalOptions="End" />
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
<StackLayout
|
||||
Spacing="0"
|
||||
Padding="0"
|
||||
IsVisible="{Binding SelectedProviderType, Mode=OneWay, Converter={StaticResource isNull}}">
|
||||
<Label
|
||||
Text="{u:I18n NoTwoStepAvailable}"
|
||||
Margin="20, 0"
|
||||
HorizontalTextAlignment="Center" />
|
||||
</StackLayout>
|
||||
<Button Text="{u:I18n UseAnotherTwoStepMethod}"
|
||||
Clicked="Methods_Clicked"></Button>
|
||||
</StackLayout>
|
||||
</ScrollView>
|
||||
|
||||
</pages:BaseContentPage>
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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<IStorageService>("storageService");
|
||||
_apiService = ServiceContainer.Resolve<IApiService>("apiService");
|
||||
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
|
||||
_environmentService = ServiceContainer.Resolve<IEnvironmentService>("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;
|
||||
|
|
Loading…
Reference in a new issue