From f153c7509cd0c51a561a323bfbf32345144d3118 Mon Sep 17 00:00:00 2001 From: kspearrin Date: Fri, 21 Sep 2018 11:22:06 -0400 Subject: [PATCH] build identity store for quick type bar --- .../CredentialProviderViewController.cs | 2 + src/iOS.Autofill/Info.plist | 2 + .../Controllers/LoginAddViewController.cs | 1 - src/iOS.Core/Utilities/ASHelpers.cs | 72 +++++++++++++++++++ src/iOS.Core/iOS.Core.csproj | 1 + src/iOS/AppDelegate.cs | 45 +++++++++--- src/iOS/Entitlements.plist | 8 +-- 7 files changed, 118 insertions(+), 13 deletions(-) create mode 100644 src/iOS.Core/Utilities/ASHelpers.cs diff --git a/src/iOS.Autofill/CredentialProviderViewController.cs b/src/iOS.Autofill/CredentialProviderViewController.cs index 42f321b2e..cc299be76 100644 --- a/src/iOS.Autofill/CredentialProviderViewController.cs +++ b/src/iOS.Autofill/CredentialProviderViewController.cs @@ -147,6 +147,8 @@ namespace Bit.iOS.Autofill public override void PrepareInterfaceForExtensionConfiguration() { base.PrepareInterfaceForExtensionConfiguration(); + var task = ASHelpers.ReplaceAllIdentities(Resolver.Resolve()); + ExtensionContext.CompleteExtensionConfigurationRequest(); } public void CompleteRequest(string username = null, string password = null, string totp = null) diff --git a/src/iOS.Autofill/Info.plist b/src/iOS.Autofill/Info.plist index 26f9ddaa9..7c064f56b 100644 --- a/src/iOS.Autofill/Info.plist +++ b/src/iOS.Autofill/Info.plist @@ -22,6 +22,8 @@ MainInterface NSExtensionPointIdentifier com.apple.authentication-services-credential-provider-ui + ASCredentialProviderExtensionShowsConfigurationUI + UIDeviceFamily diff --git a/src/iOS.Core/Controllers/LoginAddViewController.cs b/src/iOS.Core/Controllers/LoginAddViewController.cs index 49ca2504b..b35e53b8c 100644 --- a/src/iOS.Core/Controllers/LoginAddViewController.cs +++ b/src/iOS.Core/Controllers/LoginAddViewController.cs @@ -23,7 +23,6 @@ namespace Bit.iOS.Core.Controllers private IConnectivity _connectivity; private IEnumerable _folders; protected IGoogleAnalyticsService _googleAnalyticsService; - private bool _isAutofill; public LoginAddViewController(IntPtr handle) : base(handle) { diff --git a/src/iOS.Core/Utilities/ASHelpers.cs b/src/iOS.Core/Utilities/ASHelpers.cs new file mode 100644 index 000000000..b67b3435c --- /dev/null +++ b/src/iOS.Core/Utilities/ASHelpers.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using AuthenticationServices; +using Bit.App.Abstractions; +using Bit.App.Models; + +namespace Bit.iOS.Core.Utilities +{ + public static class ASHelpers + { + public static async Task ReplaceAllIdentities(ICipherService cipherService) + { + if (await AutofillEnabled()) + { + var identities = new List(); + var ciphers = await cipherService.GetAllAsync(); + foreach (var cipher in ciphers) + { + var identity = ToCredentialIdentity(cipher); + if (identity != null) + { + identities.Add(identity); + } + } + if (identities.Any()) + { + await ASCredentialIdentityStore.SharedStore.ReplaceCredentialIdentitiesAsync(identities.ToArray()); + } + } + } + + public static async Task IdentitiesCanIncremental() + { + var state = await ASCredentialIdentityStore.SharedStore.GetCredentialIdentityStoreStateAsync(); + return state.Enabled && state.SupportsIncrementalUpdates; + } + + public static async Task AutofillEnabled() + { + var state = await ASCredentialIdentityStore.SharedStore.GetCredentialIdentityStoreStateAsync(); + return state.Enabled; + } + + public static async Task GetCipherIdentityAsync(string cipherId, ICipherService cipherService) + { + var cipher = await cipherService.GetByIdAsync(cipherId); + return ToCredentialIdentity(cipher); + } + + public static ASPasswordCredentialIdentity ToCredentialIdentity(Cipher cipher) + { + if (!cipher?.Login?.Uris?.Any() ?? true) + { + return null; + } + var uri = cipher.Login.Uris.FirstOrDefault()?.Uri?.Decrypt(cipher.OrganizationId); + if (string.IsNullOrWhiteSpace(uri)) + { + return null; + } + var username = cipher.Login.Username?.Decrypt(cipher.OrganizationId); + if (string.IsNullOrWhiteSpace(username)) + { + return null; + } + var serviceId = new ASCredentialServiceIdentifier(uri, ASCredentialServiceIdentifierType.Url); + return new ASPasswordCredentialIdentity(serviceId, username, cipher.Id); + } + } +} diff --git a/src/iOS.Core/iOS.Core.csproj b/src/iOS.Core/iOS.Core.csproj index 4ab5b3ecf..da54de2ca 100644 --- a/src/iOS.Core/iOS.Core.csproj +++ b/src/iOS.Core/iOS.Core.csproj @@ -73,6 +73,7 @@ + diff --git a/src/iOS/AppDelegate.cs b/src/iOS/AppDelegate.cs index c54509b54..d32636051 100644 --- a/src/iOS/AppDelegate.cs +++ b/src/iOS/AppDelegate.cs @@ -21,6 +21,12 @@ using SimpleInjector; using XLabs.Ioc.SimpleInjectorContainer; using CoreNFC; using Bit.App.Resources; +using AuthenticationServices; +using System.Threading.Tasks; +using Bit.App.Models; +using System.Linq; +using System.Collections.Generic; +using Bit.iOS.Core.Utilities; namespace Bit.iOS { @@ -31,6 +37,7 @@ namespace Bit.iOS private NFCNdefReaderSession _nfcSession = null; private ILockService _lockService; private IDeviceInfoService _deviceInfoService; + private ICipherService _cipherService; private iOSPushNotificationHandler _pushHandler = null; private NFCReaderDelegate _nfcDelegate = null; @@ -47,6 +54,7 @@ namespace Bit.iOS _lockService = Resolver.Resolve(); _deviceInfoService = Resolver.Resolve(); + _cipherService = Resolver.Resolve(); _pushHandler = new iOSPushNotificationHandler(Resolver.Resolve()); _nfcDelegate = new NFCReaderDelegate((success, message) => ProcessYubikey(success, message)); var appIdService = Resolver.Resolve(); @@ -139,30 +147,51 @@ namespace Bit.iOS }); MessagingCenter.Subscribe( - Xamarin.Forms.Application.Current, "FullSyncCompleted", (sender, successfully) => + Xamarin.Forms.Application.Current, "FullSyncCompleted", async (sender, successfully) => { if(successfully) { - + await ASHelpers.ReplaceAllIdentities(_cipherService); } }); MessagingCenter.Subscribe( - Xamarin.Forms.Application.Current, "UpsertedCipher", (sender, id) => + Xamarin.Forms.Application.Current, "UpsertedCipher", async (sender, id) => { - + if (await ASHelpers.IdentitiesCanIncremental()) + { + var identity = await ASHelpers.GetCipherIdentityAsync(id, _cipherService); + if(identity == null) { + return; + } + await ASCredentialIdentityStore.SharedStore.SaveCredentialIdentitiesAsync( + new ASPasswordCredentialIdentity[] { identity }); + } + else + { + await ASHelpers.ReplaceAllIdentities(_cipherService); + } }); MessagingCenter.Subscribe( - Xamarin.Forms.Application.Current, "DeletedCipher", (sender, id) => + Xamarin.Forms.Application.Current, "DeletedCipher", async (sender, id) => { - + if(await ASHelpers.IdentitiesCanIncremental()) + { + var identity = new ASPasswordCredentialIdentity(null, null, id); + await ASCredentialIdentityStore.SharedStore.RemoveCredentialIdentitiesAsync( + new ASPasswordCredentialIdentity[] { identity }); + } + else + { + await ASHelpers.ReplaceAllIdentities(_cipherService); + } }); MessagingCenter.Subscribe( - Xamarin.Forms.Application.Current, "LoggedOut", (sender) => + Xamarin.Forms.Application.Current, "LoggedOut", async (sender) => { - + await ASCredentialIdentityStore.SharedStore.RemoveAllCredentialIdentitiesAsync(); }); ZXing.Net.Mobile.Forms.iOS.Platform.Init(); diff --git a/src/iOS/Entitlements.plist b/src/iOS/Entitlements.plist index edfb95f5e..bafb5af24 100644 --- a/src/iOS/Entitlements.plist +++ b/src/iOS/Entitlements.plist @@ -12,10 +12,10 @@ $(AppIdentifierPrefix)com.8bit.bitwarden - com.apple.developer.ubiquity-container-identifiers - - iCloud.$(CFBundleIdentifier) - + com.apple.developer.ubiquity-container-identifiers + + iCloud.$(CFBundleIdentifier) + com.apple.developer.nfc.readersession.formats NDEF