Add YubiKey keyboard support (#248)

* App: Pages: Fix the YubiKey image source

Signed-off-by: Alistair Francis <alistair@alistair23.me>

* App: Allow YubiKey keyboard output on apps

On Android and UWP it's possible to use the YubiKey to enter text
instead of using the NFC. Allow people to do that.

Signed-off-by: Alistair Francis <alistair@alistair23.me>

* App: Pages: Enable YubiKey support on Windows platforms

Windows platforms should always have YubiKey support.

Signed-off-by: Alistair Francis <alistair@alistair23.me>
This commit is contained in:
Alistair Francis 2018-01-18 04:55:06 -08:00 committed by Kyle Spearrin
parent 014bf7777b
commit 3f31d78db1
3 changed files with 24 additions and 13 deletions

View file

@ -93,6 +93,12 @@ namespace Bit.App.Pages
On = false On = false
}; };
var continueToolbarItem = new ToolbarItem(AppResources.Continue, Helpers.ToolbarImage("ion_chevron_right.png"), async () =>
{
var token = TokenCell?.Entry.Text.Trim().Replace(" ", "");
await LogInAsync(token);
}, ToolbarItemOrder.Default, 0);
if(!_providerType.HasValue) if(!_providerType.HasValue)
{ {
instruction.Text = AppResources.NoTwoStepAvailable; instruction.Text = AppResources.NoTwoStepAvailable;
@ -111,12 +117,6 @@ namespace Bit.App.Pages
else if(_providerType.Value == TwoFactorProviderType.Authenticator || else if(_providerType.Value == TwoFactorProviderType.Authenticator ||
_providerType.Value == TwoFactorProviderType.Email) _providerType.Value == TwoFactorProviderType.Email)
{ {
var continueToolbarItem = new ToolbarItem(AppResources.Continue, Helpers.ToolbarImage("login.png"), async () =>
{
var token = TokenCell?.Entry.Text.Trim().Replace(" ", "");
await LogInAsync(token);
}, ToolbarItemOrder.Default, 0);
var padding = Helpers.OnPlatform( var padding = Helpers.OnPlatform(
iOS: new Thickness(15, 20), iOS: new Thickness(15, 20),
Android: new Thickness(15, 8), Android: new Thickness(15, 8),
@ -232,7 +232,7 @@ namespace Bit.App.Pages
var image = new CachedImage var image = new CachedImage
{ {
Source = "yubikey", Source = "yubikey.png",
VerticalOptions = LayoutOptions.Start, VerticalOptions = LayoutOptions.Start,
HorizontalOptions = LayoutOptions.Center, HorizontalOptions = LayoutOptions.Center,
WidthRequest = 266, WidthRequest = 266,
@ -240,9 +240,14 @@ namespace Bit.App.Pages
Margin = new Thickness(0, 0, 0, 25) Margin = new Thickness(0, 0, 0, 25)
}; };
TokenCell = new FormEntryCell("", imageSource: "lock");
TokenCell.Entry.ReturnType = ReturnType.Go;
var table = new TwoFactorTable( var table = new TwoFactorTable(
new TableSection(Helpers.GetEmptyTableSectionTitle()) new TableSection(Helpers.GetEmptyTableSectionTitle())
{ {
TokenCell,
RememberCell RememberCell
}); });
@ -254,6 +259,7 @@ namespace Bit.App.Pages
table.WrappingStackLayout = () => layout; table.WrappingStackLayout = () => layout;
scrollView.Content = layout; scrollView.Content = layout;
ToolbarItems.Add(continueToolbarItem);
Title = AppResources.YubiKeyTitle; Title = AppResources.YubiKeyTitle;
Content = scrollView; Content = scrollView;
@ -270,6 +276,11 @@ namespace Bit.App.Pages
{ {
_deviceActionService.DismissKeyboard(); _deviceActionService.DismissKeyboard();
} }
if(TokenCell != null)
{
TokenCell.Entry.FocusWithDelay();
}
} }
private void InitEvents() private void InitEvents()
@ -312,7 +323,7 @@ namespace Bit.App.Pages
{ {
var nfcKey = _providers[TwoFactorProviderType.YubiKey].ContainsKey("Nfc") && var nfcKey = _providers[TwoFactorProviderType.YubiKey].ContainsKey("Nfc") &&
(bool)_providers[TwoFactorProviderType.YubiKey]["Nfc"]; (bool)_providers[TwoFactorProviderType.YubiKey]["Nfc"];
if(_deviceInfoService.NfcEnabled && nfcKey) if(_deviceInfoService.NfcEnabled && nfcKey || Device.RuntimePlatform == Device.UWP)
{ {
options.Add(AppResources.YubiKeyTitle); options.Add(AppResources.YubiKeyTitle);
} }
@ -453,7 +464,7 @@ namespace Bit.App.Pages
break; break;
case TwoFactorProviderType.YubiKey: case TwoFactorProviderType.YubiKey:
var nfcKey = p.Value.ContainsKey("Nfc") && (bool)p.Value["Nfc"]; var nfcKey = p.Value.ContainsKey("Nfc") && (bool)p.Value["Nfc"];
if(!_deviceInfoService.NfcEnabled || !nfcKey) if((!_deviceInfoService.NfcEnabled || !nfcKey) && Device.RuntimePlatform != Device.UWP)
{ {
continue; continue;
} }

View file

@ -3148,7 +3148,7 @@ namespace Bit.App.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Hold your YubiKey NEO against the back of the device to continue.. /// Looks up a localized string similar to To continue, hold your YubiKey NEO against the back of the device or insert your YubiKey into your device&apos;s USB port, then touch its button..
/// </summary> /// </summary>
public static string YubiKeyInstruction { public static string YubiKeyInstruction {
get { get {
@ -3157,7 +3157,7 @@ namespace Bit.App.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to YubiKey NEO Security Key. /// Looks up a localized string similar to YubiKey Security Key.
/// </summary> /// </summary>
public static string YubiKeyTitle { public static string YubiKeyTitle {
get { get {

View file

@ -883,10 +883,10 @@
<comment>For 2FA</comment> <comment>For 2FA</comment>
</data> </data>
<data name="YubiKeyInstruction" xml:space="preserve"> <data name="YubiKeyInstruction" xml:space="preserve">
<value>Hold your YubiKey NEO against the back of the device to continue.</value> <value>To continue, hold your YubiKey NEO against the back of the device or insert your YubiKey into your device's USB port, then touch its button.</value>
</data> </data>
<data name="YubiKeyTitle" xml:space="preserve"> <data name="YubiKeyTitle" xml:space="preserve">
<value>YubiKey NEO Security Key</value> <value>YubiKey Security Key</value>
<comment>"YubiKey NEO" is the product name and should not be translated.</comment> <comment>"YubiKey NEO" is the product name and should not be translated.</comment>
</data> </data>
<data name="AddNewAttachment" xml:space="preserve"> <data name="AddNewAttachment" xml:space="preserve">