mirror of
https://github.com/bitwarden/mobile.git
synced 2024-12-18 15:37:42 +01:00
listen to yubikey
This commit is contained in:
parent
822fc7f308
commit
58d101659a
@ -32,6 +32,8 @@ namespace Bit.Droid
|
|||||||
private IBroadcasterService _broadcasterService;
|
private IBroadcasterService _broadcasterService;
|
||||||
private PendingIntent _lockAlarmPendingIntent;
|
private PendingIntent _lockAlarmPendingIntent;
|
||||||
private AppOptions _appOptions;
|
private AppOptions _appOptions;
|
||||||
|
private Java.Util.Regex.Pattern _otpPattern =
|
||||||
|
Java.Util.Regex.Pattern.Compile("^.*?([cbdefghijklnrtuv]{32,64})$");
|
||||||
|
|
||||||
protected override void OnCreate(Bundle savedInstanceState)
|
protected override void OnCreate(Bundle savedInstanceState)
|
||||||
{
|
{
|
||||||
@ -70,9 +72,38 @@ namespace Bit.Droid
|
|||||||
{
|
{
|
||||||
Finish();
|
Finish();
|
||||||
}
|
}
|
||||||
|
else if(message.Command == "listenYubiKeyOTP")
|
||||||
|
{
|
||||||
|
ListenYubiKey((bool)message.Data);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void OnPause()
|
||||||
|
{
|
||||||
|
base.OnPause();
|
||||||
|
ListenYubiKey(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnResume()
|
||||||
|
{
|
||||||
|
base.OnResume();
|
||||||
|
if(_deviceActionService.SupportsNfc())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_messagingService.Send("resumeYubiKey");
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnNewIntent(Intent intent)
|
||||||
|
{
|
||||||
|
base.OnNewIntent(intent);
|
||||||
|
ParseYubiKey(intent.DataString);
|
||||||
|
}
|
||||||
|
|
||||||
public async override void OnRequestPermissionsResult(int requestCode, string[] permissions,
|
public async override void OnRequestPermissionsResult(int requestCode, string[] permissions,
|
||||||
[GeneratedEnum] Permission[] grantResults)
|
[GeneratedEnum] Permission[] grantResults)
|
||||||
{
|
{
|
||||||
@ -191,5 +222,19 @@ namespace Bit.Droid
|
|||||||
}
|
}
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ParseYubiKey(string data)
|
||||||
|
{
|
||||||
|
if(data == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var otpMatch = _otpPattern.Matcher(data);
|
||||||
|
if(otpMatch.Matches())
|
||||||
|
{
|
||||||
|
var otp = otpMatch.Group(1);
|
||||||
|
_messagingService.Send("gotYubiKeyOTP", otp);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,28 @@
|
|||||||
using Bit.App.Controls;
|
using Bit.App.Controls;
|
||||||
|
using Bit.Core.Abstractions;
|
||||||
|
using Bit.Core.Utilities;
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Xamarin.Forms;
|
||||||
|
|
||||||
namespace Bit.App.Pages
|
namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
public partial class TwoFactorPage : BaseContentPage
|
public partial class TwoFactorPage : BaseContentPage
|
||||||
{
|
{
|
||||||
|
private readonly IBroadcasterService _broadcasterService;
|
||||||
|
private readonly IMessagingService _messagingService;
|
||||||
|
|
||||||
private TwoFactorPageViewModel _vm;
|
private TwoFactorPageViewModel _vm;
|
||||||
|
|
||||||
public TwoFactorPage()
|
public TwoFactorPage()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
SetActivityIndicator();
|
||||||
|
_broadcasterService = ServiceContainer.Resolve<IBroadcasterService>("broadcasterService");
|
||||||
|
_messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
|
||||||
_vm = BindingContext as TwoFactorPageViewModel;
|
_vm = BindingContext as TwoFactorPageViewModel;
|
||||||
_vm.Page = this;
|
_vm.Page = this;
|
||||||
DuoWebView = _duoWebView;
|
DuoWebView = _duoWebView;
|
||||||
SetActivityIndicator();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public HybridWebView DuoWebView { get; set; }
|
public HybridWebView DuoWebView { get; set; }
|
||||||
@ -34,9 +42,28 @@ namespace Bit.App.Pages
|
|||||||
ToolbarItems.Remove(_continueItem);
|
ToolbarItems.Remove(_continueItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async override void OnAppearing()
|
protected async override void OnAppearing()
|
||||||
{
|
{
|
||||||
base.OnAppearing();
|
base.OnAppearing();
|
||||||
|
_broadcasterService.Subscribe(nameof(TwoFactorPage), async (message) =>
|
||||||
|
{
|
||||||
|
if(message.Command == "gotYubiKeyOTP")
|
||||||
|
{
|
||||||
|
if(_vm.YubikeyMethod)
|
||||||
|
{
|
||||||
|
_vm.Token = (string)message.Data;
|
||||||
|
await _vm.SubmitAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(message.Command == "resumeYubiKey")
|
||||||
|
{
|
||||||
|
if(_vm.YubikeyMethod)
|
||||||
|
{
|
||||||
|
_messagingService.Send("listenYubiKeyOTP", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
await LoadOnAppearedAsync(_scrollView, true, () =>
|
await LoadOnAppearedAsync(_scrollView, true, () =>
|
||||||
{
|
{
|
||||||
_vm.Init();
|
_vm.Init();
|
||||||
@ -44,6 +71,31 @@ namespace Bit.App.Pages
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void OnDisappearing()
|
||||||
|
{
|
||||||
|
base.OnDisappearing();
|
||||||
|
if(!_vm.YubikeyMethod)
|
||||||
|
{
|
||||||
|
_messagingService.Send("listenYubiKeyOTP", false);
|
||||||
|
_broadcasterService.Unsubscribe(nameof(TwoFactorPage));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool OnBackButtonPressed()
|
||||||
|
{
|
||||||
|
// ref: https://github.com/bitwarden/mobile/issues/350
|
||||||
|
if(_vm.YubikeyMethod)
|
||||||
|
{
|
||||||
|
if(Device.RuntimePlatform == Device.Android)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
_messagingService.Send("listenYubiKeyOTP", false);
|
||||||
|
_broadcasterService.Unsubscribe(nameof(TwoFactorPage));
|
||||||
|
}
|
||||||
|
return base.OnBackButtonPressed();
|
||||||
|
}
|
||||||
|
|
||||||
private async void Continue_Clicked(object sender, EventArgs e)
|
private async void Continue_Clicked(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if(DoOnce())
|
if(DoOnce())
|
||||||
|
@ -21,6 +21,8 @@ namespace Bit.App.Pages
|
|||||||
private readonly IApiService _apiService;
|
private readonly IApiService _apiService;
|
||||||
private readonly IPlatformUtilsService _platformUtilsService;
|
private readonly IPlatformUtilsService _platformUtilsService;
|
||||||
private readonly IEnvironmentService _environmentService;
|
private readonly IEnvironmentService _environmentService;
|
||||||
|
private readonly IMessagingService _messagingService;
|
||||||
|
private readonly IBroadcasterService _broadcasterService;
|
||||||
|
|
||||||
private bool _u2fSupported = false;
|
private bool _u2fSupported = false;
|
||||||
private TwoFactorProviderType? _selectedProviderType;
|
private TwoFactorProviderType? _selectedProviderType;
|
||||||
@ -36,6 +38,8 @@ namespace Bit.App.Pages
|
|||||||
_apiService = ServiceContainer.Resolve<IApiService>("apiService");
|
_apiService = ServiceContainer.Resolve<IApiService>("apiService");
|
||||||
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
|
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
|
||||||
_environmentService = ServiceContainer.Resolve<IEnvironmentService>("environmentService");
|
_environmentService = ServiceContainer.Resolve<IEnvironmentService>("environmentService");
|
||||||
|
_messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
|
||||||
|
_broadcasterService = ServiceContainer.Resolve<IBroadcasterService>("broadcasterService");
|
||||||
|
|
||||||
PageTitle = AppResources.TwoStepLogin;
|
PageTitle = AppResources.TwoStepLogin;
|
||||||
}
|
}
|
||||||
@ -122,9 +126,11 @@ namespace Bit.App.Pages
|
|||||||
case TwoFactorProviderType.U2f:
|
case TwoFactorProviderType.U2f:
|
||||||
// TODO
|
// TODO
|
||||||
break;
|
break;
|
||||||
|
case TwoFactorProviderType.YubiKey:
|
||||||
|
_messagingService.Send("listenYubiKeyOTP", true);
|
||||||
|
break;
|
||||||
case TwoFactorProviderType.Duo:
|
case TwoFactorProviderType.Duo:
|
||||||
case TwoFactorProviderType.OrganizationDuo:
|
case TwoFactorProviderType.OrganizationDuo:
|
||||||
page.RemoveContinueButton();
|
|
||||||
var host = WebUtility.UrlEncode(providerData["Host"] as string);
|
var host = WebUtility.UrlEncode(providerData["Host"] as string);
|
||||||
var req = WebUtility.UrlEncode(providerData["Signature"] as string);
|
var req = WebUtility.UrlEncode(providerData["Signature"] as string);
|
||||||
page.DuoWebView.Uri = $"{_webVaultUrl}/duo-connector.html?host={host}&request={req}";
|
page.DuoWebView.Uri = $"{_webVaultUrl}/duo-connector.html?host={host}&request={req}";
|
||||||
@ -135,7 +141,6 @@ namespace Bit.App.Pages
|
|||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case TwoFactorProviderType.Email:
|
case TwoFactorProviderType.Email:
|
||||||
page.AddContinueButton();
|
|
||||||
TwoFactorEmail = providerData["Email"] as string;
|
TwoFactorEmail = providerData["Email"] as string;
|
||||||
if(_authService.TwoFactorProvidersData.Count > 1)
|
if(_authService.TwoFactorProvidersData.Count > 1)
|
||||||
{
|
{
|
||||||
@ -143,9 +148,21 @@ namespace Bit.App.Pages
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
page.AddContinueButton();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!YubikeyMethod)
|
||||||
|
{
|
||||||
|
_messagingService.Send("listenYubiKeyOTP", false);
|
||||||
|
}
|
||||||
|
if(DuoMethod)
|
||||||
|
{
|
||||||
|
page.RemoveContinueButton();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
page.AddContinueButton();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SubmitAsync()
|
public async Task SubmitAsync()
|
||||||
@ -172,6 +189,8 @@ namespace Bit.App.Pages
|
|||||||
await _authService.LogInTwoFactorAsync(SelectedProviderType.Value, Token, Remember);
|
await _authService.LogInTwoFactorAsync(SelectedProviderType.Value, Token, Remember);
|
||||||
await _deviceActionService.HideLoadingAsync();
|
await _deviceActionService.HideLoadingAsync();
|
||||||
var task = Task.Run(() => _syncService.FullSyncAsync(true));
|
var task = Task.Run(() => _syncService.FullSyncAsync(true));
|
||||||
|
_messagingService.Send("listenYubiKeyOTP", false);
|
||||||
|
_broadcasterService.Unsubscribe(nameof(TwoFactorPage));
|
||||||
Application.Current.MainPage = new TabsPage();
|
Application.Current.MainPage = new TabsPage();
|
||||||
}
|
}
|
||||||
catch(ApiException e)
|
catch(ApiException e)
|
||||||
@ -202,7 +221,7 @@ namespace Bit.App.Pages
|
|||||||
|
|
||||||
public async Task<bool> SendEmailAsync(bool showLoading, bool doToast)
|
public async Task<bool> SendEmailAsync(bool showLoading, bool doToast)
|
||||||
{
|
{
|
||||||
if(SelectedProviderType != TwoFactorProviderType.Email)
|
if(!EmailMethod)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,6 @@ namespace Bit.App.Pages
|
|||||||
protected async override void OnAppearing()
|
protected async override void OnAppearing()
|
||||||
{
|
{
|
||||||
base.OnAppearing();
|
base.OnAppearing();
|
||||||
// await _syncService.FullSyncAsync(true);
|
|
||||||
_broadcasterService.Subscribe(_pageName, async (message) =>
|
_broadcasterService.Subscribe(_pageName, async (message) =>
|
||||||
{
|
{
|
||||||
if(message.Command == "syncCompleted")
|
if(message.Command == "syncCompleted")
|
||||||
|
Loading…
Reference in New Issue
Block a user