Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PM-3811] Passkeys unification #2774

Merged
merged 7 commits into from
Sep 22, 2023
36 changes: 2 additions & 34 deletions src/App/Pages/Vault/CipherAddEditPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -229,9 +229,9 @@
Margin="0,10,0,0"
IsVisible="{Binding ShowPasskeyInfo}"/>
<Entry
Text="{u:I18n AvailableForTwoStepLogin}"
Text="{Binding CreationDate}"
IsEnabled="False"
StyleClass="box-value,text-muted"
StyleClass="box-value,text-muted"
IsVisible="{Binding ShowPasskeyInfo}" />

<Grid StyleClass="box-row, box-row-input">
Expand Down Expand Up @@ -650,38 +650,6 @@
AutomationId="IdentityCountryEntry" />
</StackLayout>
</StackLayout>

<StackLayout IsVisible="{Binding IsFido2Key}" Spacing="0" Padding="0">
<Label
Text="{u:I18n Username}"
StyleClass="box-label"
Margin="0,10,0,0"/>
<Entry
x:Name="_fido2KeyUsernameEntry"
Text="{Binding Cipher.Fido2Key.UserName}"
StyleClass="box-value"
Grid.Row="1"/>
<Label
Text="{u:I18n Passkey}"
StyleClass="box-label"
Margin="0,10,0,0"/>
<Entry
Text="{Binding CreationDate}"
IsEnabled="False"
StyleClass="box-value,text-muted" />
<Label
Text="{u:I18n Application}"
StyleClass="box-label"
Margin="0,10,0,0"/>
<Entry
Text="{Binding Cipher.Fido2Key.LaunchUri}"
IsEnabled="False"
StyleClass="box-value,text-muted" />
<Label
Text="{u:I18n YouCannotEditPasskeyApplicationBecauseItWouldInvalidateThePasskey}"
StyleClass="box-sub-label" />
</StackLayout>

</StackLayout>
<StackLayout StyleClass="box" IsVisible="{Binding IsLogin}">
<StackLayout StyleClass="box-row-header">
Expand Down
5 changes: 2 additions & 3 deletions src/App/Pages/Vault/CipherAddEditPageViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,6 @@ public bool HasCollections
public bool IsIdentity => Cipher?.Type == CipherType.Identity;
public bool IsCard => Cipher?.Type == CipherType.Card;
public bool IsSecureNote => Cipher?.Type == CipherType.SecureNote;
public bool IsFido2Key => Cipher?.Type == CipherType.Fido2Key;
public bool ShowUris => IsLogin && Cipher.Login.HasUris;
public bool ShowAttachments => Cipher.HasAttachments;
public string ShowPasswordIcon => ShowPassword ? BitwardenIcons.EyeSlash : BitwardenIcons.Eye;
Expand All @@ -309,7 +308,7 @@ public bool HasCollections
public string PasswordVisibilityAccessibilityText => ShowPassword ? AppResources.PasswordIsVisibleTapToHide : AppResources.PasswordIsNotVisibleTapToShow;
public bool HasTotpValue => IsLogin && !string.IsNullOrEmpty(Cipher?.Login?.Totp);
public string SetupTotpText => $"{BitwardenIcons.Camera} {AppResources.SetupTotp}";
public bool ShowPasskeyInfo => Cipher?.Login?.Fido2Key != null && !CloneMode;
public bool ShowPasskeyInfo => Cipher?.HasFido2Key == true && !CloneMode;

public void Init()
{
Expand Down Expand Up @@ -371,7 +370,7 @@ public async Task<bool> LoadAsync(AppOptions appOptions = null)
if (Cipher.Type == CipherType.Login)
{
// passkeys can't be cloned
Cipher.Login.Fido2Key = null;
Cipher.Login.Fido2Keys = null;
}
}
if (appOptions?.OtpData != null && Cipher.Type == CipherType.Login)
Expand Down
64 changes: 3 additions & 61 deletions src/App/Pages/Vault/CipherDetailsPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -199,12 +199,12 @@
Text="{u:I18n Passkey}"
StyleClass="box-label"
Margin="0,10,0,0"
IsVisible="{Binding Cipher.Login.Fido2Key, Converter={StaticResource notNull}}"/>
IsVisible="{Binding Cipher.Login.MainFido2Key, Converter={StaticResource notNull}}"/>
<Entry
Text="{u:I18n AvailableForTwoStepLogin}"
Text="{Binding CreationDate}"
IsEnabled="False"
StyleClass="box-value,text-muted"
IsVisible="{Binding Cipher.Login.Fido2Key, Converter={StaticResource notNull}}" />
IsVisible="{Binding Cipher.Login.MainFido2Key, Converter={StaticResource notNull}}" />
<Grid StyleClass="box-row"
IsVisible="{Binding ShowTotp}"
AutomationId="ItemRow">
Expand Down Expand Up @@ -579,64 +579,6 @@
</StackLayout>
<BoxView StyleClass="box-row-separator" IsVisible="{Binding ShowIdentityAddress}" />
</StackLayout>
<StackLayout
IsVisible="{Binding IsFido2Key}"
Spacing="0"
Padding="0"
Margin="0,10,0,0">
<Label
Text="{u:I18n Username}"
StyleClass="box-label" />
<Label
Text="{Binding Cipher.Fido2Key.UserName, Mode=OneWay}"
StyleClass="box-value" />
<BoxView StyleClass="box-row-separator" Margin="0,10,0,0" />
<Label
Text="{u:I18n Passkey}"
StyleClass="box-label"
Margin="0,10,0,0" />
<Label
Text="{Binding CreationDate, Mode=OneWay}"
StyleClass="box-value" />
<BoxView StyleClass="box-row-separator" Margin="0,10,0,0" />
<Grid
StyleClass="box-row"
RowDefinitions="Auto,*,Auto"
ColumnDefinitions="*,Auto,Auto">
<Label
Text="{u:I18n Application}"
StyleClass="box-label" />
<Label
Grid.Row="1"
Text="{Binding Cipher.Fido2Key.LaunchUri, Mode=OneWay}"
StyleClass="box-value" />
<controls:IconButton
StyleClass="box-row-button, box-row-button-platform"
Text="{Binding Source={x:Static core:BitwardenIcons.ShareSquare}}"
Command="{Binding LaunchUriCommand}"
CommandParameter="{Binding Cipher.Fido2Key}"
Grid.Column="1"
Grid.RowSpan="2"
VerticalOptions="End"
IsVisible="{Binding Cipher.Fido2Key.CanLaunch, Mode=OneWay}"
AutomationProperties.IsInAccessibleTree="True"
AutomationProperties.Name="{u:I18n Launch}" />
<controls:IconButton
StyleClass="box-row-button, box-row-button-platform"
Text="{Binding Source={x:Static core:BitwardenIcons.Clone}}"
Command="{Binding CopyCommand}"
CommandParameter="Fido2KeyApplication"
Grid.Column="2"
Grid.RowSpan="2"
AutomationProperties.IsInAccessibleTree="True"
AutomationProperties.Name="{u:I18n CopyApplication}" />
<BoxView
StyleClass="box-row-separator"
Margin="0,3,0,0"
Grid.Row="2"
Grid.ColumnSpan="3" />
</Grid>
</StackLayout>
</StackLayout>
<StackLayout StyleClass="box" IsVisible="{Binding ShowUris}">
<StackLayout StyleClass="box-row-header">
Expand Down
18 changes: 3 additions & 15 deletions src/App/Pages/Vault/CipherDetailsPageViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,6 @@ public bool ShowCardCode
public bool IsIdentity => Cipher?.Type == Core.Enums.CipherType.Identity;
public bool IsCard => Cipher?.Type == Core.Enums.CipherType.Card;
public bool IsSecureNote => Cipher?.Type == Core.Enums.CipherType.SecureNote;
public bool IsFido2Key => Cipher?.Type == Core.Enums.CipherType.Fido2Key;
public FormattedString ColoredPassword => GeneratedValueFormatter.Format(Cipher.Login.Password);
public FormattedString UpdatedText
{
Expand Down Expand Up @@ -649,11 +648,6 @@ private async Task CopyAsync(string id, string text = null)
text = Cipher.Card.Code;
name = AppResources.SecurityCode;
}
else if (id == "Fido2KeyApplication")
{
text = Cipher.Fido2Key?.LaunchUri;
name = AppResources.Application;
}

if (text != null)
{
Expand Down Expand Up @@ -708,18 +702,12 @@ public async Task<bool> PromptPasswordAsync()

private async Task<bool> CanCloneAsync()
{
if (Cipher.Type == CipherType.Fido2Key)
{
await _platformUtilsService.ShowDialogAsync(AppResources.PasskeyWillNotBeCopied);
return false;
}

if (Cipher.Type == CipherType.Login && Cipher.Login?.Fido2Key != null)
if (!Cipher.HasFido2Key)
{
return await _platformUtilsService.ShowDialogAsync(AppResources.ThePasskeyWillNotBeCopiedToTheClonedItemDoYouWantToContinueCloningThisItem, AppResources.PasskeyWillNotBeCopied, AppResources.Yes, AppResources.No);
return true;
}

return true;
return await _platformUtilsService.ShowDialogAsync(AppResources.ThePasskeyWillNotBeCopiedToTheClonedItemDoYouWantToContinueCloningThisItem, AppResources.PasskeyWillNotBeCopied, AppResources.Yes, AppResources.No);
}
}
}
6 changes: 0 additions & 6 deletions src/App/Pages/Vault/GroupingsPage/GroupingsPageListItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,6 @@ public string Name
case CipherType.Identity:
_name = AppResources.TypeIdentity;
break;
case CipherType.Fido2Key:
_name = AppResources.Passkey;
break;
default:
break;
}
Expand Down Expand Up @@ -111,9 +108,6 @@ public string Icon
case CipherType.Identity:
_icon = BitwardenIcons.IdCard;
break;
case CipherType.Fido2Key:
_icon = BitwardenIcons.Passkey;
break;
default:
_icon = BitwardenIcons.Globe;
break;
Expand Down
6 changes: 2 additions & 4 deletions src/App/Pages/Vault/GroupingsPage/GroupingsPageViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -569,7 +569,7 @@ private async Task LoadDataAsync()
{
Filter = c => !c.IsDeleted
&&
Type.Value.IsEqualToOrCanSignIn(c.Type);
Type.Value == c.Type;
}
else if (FolderId != null)
{
Expand Down Expand Up @@ -636,9 +636,7 @@ private async Task LoadDataAsync()
NoFolderCiphers.Add(c);
}

// Fido2Key ciphers should be counted as Login ciphers
var countType = c.Type == CipherType.Fido2Key ? CipherType.Login : c.Type;
_typeCounts[countType] = _typeCounts.TryGetValue(countType, out var currentTypeCount)
_typeCounts[c.Type] = _typeCounts.TryGetValue(c.Type, out var currentTypeCount)
? currentTypeCount + 1
: 1;
}
Expand Down
13 changes: 1 addition & 12 deletions src/App/Utilities/AppHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,17 +78,6 @@ public static async Task<string> CipherListOptions(ContentPage page, CipherView
options.Add(AppResources.CopyNotes);
}
}
if (cipher.Type == Core.Enums.CipherType.Fido2Key)
{
if (!string.IsNullOrWhiteSpace(cipher.Fido2Key.UserName))
{
options.Add(AppResources.CopyUsername);
}
if (cipher.Fido2Key.CanLaunch)
{
options.Add(AppResources.Launch);
}
}

var selection = await page.DisplayActionSheet(cipher.Name, AppResources.Cancel, null, options.ToArray());
if (await vaultTimeoutService.IsLockedAsync())
Expand All @@ -107,7 +96,7 @@ await passwordRepromptService.PromptAndCheckPasswordIfNeededAsync(cipher.Repromp
}
else if (selection == AppResources.CopyUsername)
{
await clipboardService.CopyTextAsync(cipher.Type == CipherType.Login ? cipher.Login.Username : cipher.Fido2Key.UserName);
await clipboardService.CopyTextAsync(cipher.Login.Username);
platformUtilsService.ShowToastForCopiedValue(AppResources.Username);
}
else if (selection == AppResources.CopyPassword
Expand Down
2 changes: 0 additions & 2 deletions src/App/Utilities/IconGlyphExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ public static string GetIcon(this CipherView cipher)
return BitwardenIcons.CreditCard;
case CipherType.Identity:
return BitwardenIcons.IdCard;
case CipherType.Fido2Key:
return BitwardenIcons.Passkey;
}
return null;
}
Expand Down
30 changes: 4 additions & 26 deletions src/App/Utilities/IconImageConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,12 @@ public static class IconImageHelper
{
public static string GetIconImage(CipherView cipher)
{
switch (cipher.Type)
if (cipher.Type != CipherType.Login)
{
case CipherType.Login:
return IconImageHelper.GetLoginIconImage(cipher);
case CipherType.Fido2Key:
return IconImageHelper.GetFido2KeyIconImage(cipher);
return null;
}
return null;

return GetLoginIconImage(cipher);
}

public static string GetLoginIconImage(CipherView cipher)
Expand Down Expand Up @@ -65,26 +63,6 @@ public static string GetLoginIconImage(CipherView cipher)
return image;
}

public static string GetFido2KeyIconImage(CipherView cipher)
{
var hostnameUri = cipher.Fido2Key.LaunchUri;
if (!hostnameUri.Contains("."))
{
return null;
}

if (!hostnameUri.Contains("://"))
{
hostnameUri = string.Concat("https://", hostnameUri);
}
if (hostnameUri.StartsWith("http"))
{
return GetIconUrl(hostnameUri);
}

return null;
}

private static string GetIconUrl(string hostnameUri)
{
IEnvironmentService _environmentService = ServiceContainer.Resolve<IEnvironmentService>("environmentService");
Expand Down
3 changes: 1 addition & 2 deletions src/Core/Enums/CipherType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ public enum CipherType : byte
Login = 1,
SecureNote = 2,
Card = 3,
Identity = 4,
Fido2Key = 5
Identity = 4
}
}
7 changes: 4 additions & 3 deletions src/Core/Models/Api/Fido2KeyApi.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Bit.Core.Models.Domain;
using Bit.Core.Models.Export;

namespace Bit.Core.Models.Api
{
Expand All @@ -11,7 +10,8 @@ public Fido2KeyApi()

public Fido2KeyApi(Fido2Key fido2Key)
{
NonDiscoverableId = fido2Key.NonDiscoverableId?.EncryptedString;
CredentialId = fido2Key.CredentialId?.EncryptedString;
Discoverable = fido2Key.Discoverable?.EncryptedString;
KeyType = fido2Key.KeyType?.EncryptedString;
KeyAlgorithm = fido2Key.KeyAlgorithm?.EncryptedString;
KeyCurve = fido2Key.KeyCurve?.EncryptedString;
Expand All @@ -23,7 +23,8 @@ public Fido2KeyApi(Fido2Key fido2Key)
Counter = fido2Key.Counter?.EncryptedString;
}

public string NonDiscoverableId { get; set; }
public string CredentialId { get; set; }
public string Discoverable { get; set; }
public string KeyType { get; set; } = Constants.DefaultFido2KeyType;
public string KeyAlgorithm { get; set; } = Constants.DefaultFido2KeyAlgorithm;
public string KeyCurve { get; set; } = Constants.DefaultFido2KeyCurve;
Expand Down
2 changes: 1 addition & 1 deletion src/Core/Models/Api/LoginApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ public class LoginApi
public string Password { get; set; }
public DateTime? PasswordRevisionDate { get; set; }
public string Totp { get; set; }
public Fido2KeyApi Fido2Key { get; set; }
public List<Fido2KeyApi> Fido2Keys { get; set; }
}
}
4 changes: 0 additions & 4 deletions src/Core/Models/Data/CipherData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,6 @@ public CipherData(CipherResponse response, string userId = null, HashSet<string>
case Enums.CipherType.Identity:
Identity = new IdentityData(response.Identity);
break;
case Enums.CipherType.Fido2Key:
Fido2Key = new Fido2KeyData(response.Fido2Key);
break;
default:
break;
}
Expand Down Expand Up @@ -86,7 +83,6 @@ public CipherData(CipherResponse response, string userId = null, HashSet<string>
public SecureNoteData SecureNote { get; set; }
public CardData Card { get; set; }
public IdentityData Identity { get; set; }
public Fido2KeyData Fido2Key { get; set; }
public List<FieldData> Fields { get; set; }
public List<AttachmentData> Attachments { get; set; }
public List<PasswordHistoryData> PasswordHistory { get; set; }
Expand Down
Loading