/// <summary> /// Notification that is triggered after token acquisition. /// </summary> /// <param name="args">Arguments related to the cache item impacted</param> public override void AfterAccessNotification(TokenCacheNotificationArgs args) { MsalCacheStorage cacheStorage = GetMsalCacheStorage(); args.AssertNotNull(nameof(args)); try { if (args.HasStateChanged) { cacheStorage.WriteData(args.TokenCache.SerializeMsalV3()); } } catch (Exception) { cacheStorage.Clear(); throw; } finally { CrossPlatformLock localDispose = cacheLock; cacheLock = null; localDispose?.Dispose(); } }
public void ImportExport_ThrowException() { // Arrange var cacheAccessor = NSubstitute.Substitute.For <ICacheAccessor>(); var cache = new MockTokenCache(); var storage = new MsalCacheStorage( _storageCreationPropertiesBuilder.Build(), cacheAccessor, new TraceSourceLogger(new TraceSource("ts"))); var helper = new MsalCacheHelper(cache, storage, _logger); byte[] dataToSave = Encoding.UTF8.GetBytes("Hello World 2"); var ex = new InvalidCastException(); cacheAccessor.Read().Throws(ex); // Act var actualEx = AssertException.Throws <InvalidCastException>( () => helper.LoadUnencryptedTokenCache()); // Assert Assert.AreEqual(ex, actualEx); // Arrange cacheAccessor.WhenForAnyArgs(c => c.Write(default)).Throw(ex);
/// <inheritdoc /> public SharedTokenCacheProvider(IConfiguration config = null, ILogger logger = null) { _logger = logger; _config = config ?? new ConfigurationBuilder().AddEnvironmentVariables().Build(); const string serviceName = "Microsoft.Developer.IdentityService"; const string clientId = "04b07795-8ddb-461a-bbee-02f9e1bf7b46"; var storageCreationPropertiesBuilder = new StorageCreationPropertiesBuilder( Path.GetFileName(s_cacheFilePath), Path.GetDirectoryName(s_cacheFilePath), clientId) .WithMacKeyChain(serviceName: serviceName, accountName: "MSALCache") .WithLinuxKeyring( schemaName: "msal.cache", collection: "default", secretLabel: "MSALCache", attribute1: new KeyValuePair <string, string>("MsalClientID", serviceName), attribute2: new KeyValuePair <string, string>("MsalClientVersion", "1.0.0.0")); var authority = string.Format(CultureInfo.InvariantCulture, AadAuthority.AadCanonicalAuthorityTemplate, AadAuthority.DefaultTrustedHost, "common"); _app = PublicClientApplicationBuilder .Create(clientId) .WithAuthority(new Uri(authority)) .Build(); var cacheStore = new MsalCacheStorage(storageCreationPropertiesBuilder.Build()); _cacheHelper = new MsalCacheHelper(_app.UserTokenCache, cacheStore); _cacheHelper.RegisterCache(_app.UserTokenCache); }
public void MsalTestClear() { var store = new MsalCacheStorage(s_storageCreationProperties, logger: _logger); Assert.IsTrue(store.HasChanged); var tempData = store.ReadData(); Assert.IsFalse(store.HasChanged); var store2 = new MsalCacheStorage(s_storageCreationProperties, logger: _logger); Assert.IsNotNull(Exception <ArgumentNullException>(() => store.WriteData(null))); byte[] data = { 2, 2, 3 }; store.WriteData(data); Assert.IsFalse(store.HasChanged); Assert.IsTrue(store2.HasChanged); store2.ReadData(); Enumerable.SequenceEqual(store.ReadData(), data); Assert.IsTrue(File.Exists(CacheFilePath)); store.Clear(); Assert.IsFalse(store.HasChanged); Assert.IsTrue(store2.HasChanged); Assert.IsFalse(store.ReadData().Any()); Assert.IsFalse(store2.ReadData().Any()); Assert.IsFalse(File.Exists(CacheFilePath)); }
public void MsalNewStoreNoFile() { var store = new MsalCacheStorage(s_storageCreationProperties, logger: _logger); Assert.IsFalse(store.HasChanged); Assert.IsFalse(store.ReadData().Any()); }
public void CacheStorageFactory_WithFallback_Linux() { var storageWithKeyRing = new StorageCreationPropertiesBuilder( Path.GetFileName(CacheFilePath), Path.GetDirectoryName(CacheFilePath), "ClientIDGoesHere") .WithMacKeyChain(serviceName: "Microsoft.Developer.IdentityService", accountName: "MSALCache") .WithLinuxKeyring( schemaName: "msal.cache", collection: "default", secretLabel: "MSALCache", attribute1: new KeyValuePair <string, string>("MsalClientID", "Microsoft.Developer.IdentityService"), attribute2: new KeyValuePair <string, string>("MsalClientVersion", "1.0.0.0")) .Build(); // Tests run on machines without Libsecret MsalCacheStorage store = MsalCacheStorage.Create(storageWithKeyRing, logger: _logger); Assert.IsTrue(store.CacheAccessor is LinuxKeyringAccessor); // ADO Linux test agents do not have libsecret installed by default // If you run this test on a Linux box with UI / LibSecret, then this test will fail // because the statement below will not throw. AssertException.Throws <MsalCachePersistenceException>( () => store.VerifyPersistence()); store = MsalCacheStorage.Create(s_storageCreationProperties, _logger); Assert.IsTrue(store.CacheAccessor is FileAccessor); store.VerifyPersistence(); }
public void MsalWriteEmptyData() { var store = MsalCacheStorage.Create(s_storageCreationProperties, logger: _logger); Assert.ThrowsException <ArgumentNullException>(() => store.WriteData(null)); store.WriteData(new byte[0]); Assert.IsFalse(store.ReadData().Any()); }
public void CacheStorageFactoryMac() { MsalCacheStorage store = MsalCacheStorage.Create(s_storageCreationProperties, logger: _logger); Assert.IsTrue(store.CacheAccessor is MacKeychainAccessor); store.VerifyPersistence(); store = MsalCacheStorage.Create(s_storageCreationProperties, logger: _logger); Assert.IsTrue(store.CacheAccessor is MacKeychainAccessor); }
public void CacheStorageFactoryWindows() { MsalCacheStorage store = MsalCacheStorage.Create(s_storageCreationProperties, logger: _logger); Assert.IsTrue(store.CacheAccessor is DpApiEncryptedFileAccessor); store.VerifyPersistence(); store = MsalCacheStorage.Create(s_storageCreationProperties, logger: _logger); Assert.IsTrue(store.CacheAccessor is DpApiEncryptedFileAccessor); }
/// <summary> /// Gets an aptly configured instance of the <see cref="MsalCacheStorage" /> class. /// </summary> /// <returns>An aptly configured instance of the <see cref="MsalCacheStorage" /> class.</returns> private MsalCacheStorage GetMsalCacheStorage() { StorageCreationPropertiesBuilder builder = new StorageCreationPropertiesBuilder(Path.GetFileName(CacheFilePath), Path.GetDirectoryName(CacheFilePath), ClientId); builder = builder.WithMacKeyChain(serviceName: "Microsoft.Developer.IdentityService", accountName: "MSALCache"); builder = builder.WithLinuxKeyring( schemaName: "msal.cache", collection: "default", secretLabel: "MSALCache", attribute1: new KeyValuePair <string, string>("MsalClientID", "Microsoft.Developer.IdentityService"), attribute2: new KeyValuePair <string, string>("MsalClientVersion", "1.0.0.0")); return(MsalCacheStorage.Create(builder.Build(), new TraceSource("Partner Center PowerShell"))); }
public void CacheStorageReadCanHandleReadingNull() { // Arrange var cacheAccessor = NSubstitute.Substitute.For <ICacheAccessor>(); cacheAccessor.Read().Returns((byte[])null); var actualLogger = new TraceSourceLogger(_logger); var storage = new MsalCacheStorage(s_storageCreationProperties, cacheAccessor, actualLogger); // Act byte[] result = storage.ReadData(); // Assert Assert.AreEqual(0, result.Length); }
public void ClearCanThrowExceptions() { // Arrange var actualLogger = new TraceSourceLogger(_logger); var cacheAccessor = NSubstitute.Substitute.For <ICacheAccessor>(); cacheAccessor.WhenForAnyArgs(c => c.Clear()).Throw(new InvalidOperationException()); var storage = new MsalCacheStorage(s_storageCreationProperties, cacheAccessor, actualLogger); // Act storage.Clear(); // Assert AssertException.Throws <InvalidOperationException>( () => storage.Clear(ignoreExceptions: false)); }
public void MsalWriteGoodData() { var store = MsalCacheStorage.Create(s_storageCreationProperties, logger: _logger); Assert.ThrowsException <ArgumentNullException>(() => store.WriteData(null)); byte[] data = { 2, 2, 3 }; byte[] data2 = { 2, 2, 3, 4, 4 }; store.WriteData(data); Assert.IsTrue(Enumerable.SequenceEqual(store.ReadData(), data)); store.WriteData(data); store.WriteData(data2); store.WriteData(data); store.WriteData(data2); Assert.IsTrue(Enumerable.SequenceEqual(store.ReadData(), data2)); }
public void VerifyPersistenceThrowsIfDataReadIsEmpty() { // Arrange var actualLogger = new TraceSourceLogger(_logger); var cacheAccessor = Substitute.For <ICacheAccessor>(); cacheAccessor.CreateForPersistenceValidation().Returns(cacheAccessor); var storage = new MsalCacheStorage(s_storageCreationProperties, cacheAccessor, actualLogger); // Act var ex = AssertException.Throws <MsalCachePersistenceException>( () => storage.VerifyPersistence()); // Assert Assert.IsNull(ex.InnerException); // no more details available }
public void CacheStorageReadCanHandleExceptionsWhenReading() { // Arrange var cacheAccessor = NSubstitute.Substitute.For <ICacheAccessor>(); var exception = new InvalidOperationException(); cacheAccessor.Read().Throws(exception); var actualLogger = new TraceSourceLogger(_logger); var storage = new MsalCacheStorage(s_storageCreationProperties, cacheAccessor, actualLogger); // Act byte[] result = storage.ReadData(); // Assert Assert.AreEqual(0, result.Length); }
public void ReadCanThrowExceptions() { // Arrange var actualLogger = new TraceSourceLogger(_logger); var cacheAccessor = NSubstitute.Substitute.For <ICacheAccessor>(); cacheAccessor.Read().Throws(new InvalidOperationException()); var storage = new MsalCacheStorage(s_storageCreationProperties, cacheAccessor, actualLogger); // Act byte[] result = storage.ReadData(); Assert.AreEqual(0, result.Length); // Assert AssertException.Throws <InvalidOperationException>( () => storage.ReadData(ignoreExceptions: false)); }
public void CacheStorageFactory_WithFallback_Linux() { var storageWithKeyRing = new StorageCreationPropertiesBuilder( Path.GetFileName(CacheFilePath), Path.GetDirectoryName(CacheFilePath), "ClientIDGoesHere") .WithMacKeyChain(serviceName: "Microsoft.Developer.IdentityService", accountName: "MSALCache") .WithLinuxKeyring( schemaName: "msal.cache", collection: "default", secretLabel: "MSALCache", attribute1: new KeyValuePair <string, string>("MsalClientID", "Microsoft.Developer.IdentityService"), attribute2: new KeyValuePair <string, string>("MsalClientVersion", "1.0.0.0")) .Build(); // Tests run on machines without Libsecret MsalCacheStorage store = MsalCacheStorage.Create(storageWithKeyRing, logger: _logger); Assert.IsTrue(store.CacheAccessor is LinuxKeyringAccessor); // ADO Linux test agents do not have libsecret installed by default // If you run this test on a Linux box with UI / LibSecret, then this test will fail // because the statement below will not throw. AssertException.Throws <MsalCachePersistenceException>( () => store.VerifyPersistence()); MsalCacheStorage unprotectedStore = MsalCacheStorage.Create(s_storageCreationProperties, _logger); Assert.IsTrue(unprotectedStore.CacheAccessor is FileAccessor); unprotectedStore.VerifyPersistence(); unprotectedStore.WriteData(new byte[] { 2, 3 }); // Unproteced cache file should exist Assert.IsTrue(File.Exists(unprotectedStore.CacheFilePath)); // Mimic another sdk client to check libsecret availability by calling // MsalCacheStorage.VerifyPeristence() -> LinuxKeyringAccessor.CreateForPersistenceValidation() AssertException.Throws <MsalCachePersistenceException>( () => store.VerifyPersistence()); // Verify above call doesn't delete existing cache file Assert.IsTrue(File.Exists(unprotectedStore.CacheFilePath)); }
public void VerifyPersistenceThrowsInnerExceptions() { // Arrange var actualLogger = new TraceSourceLogger(_logger); var cacheAccessor = Substitute.For <ICacheAccessor>(); cacheAccessor.CreateForPersistenceValidation().Returns(cacheAccessor); var exception = new InvalidOperationException("some error"); var storage = new MsalCacheStorage(s_storageCreationProperties, cacheAccessor, actualLogger); cacheAccessor.Read().Throws(exception); // Act var ex = AssertException.Throws <MsalCachePersistenceException>( () => storage.VerifyPersistence()); // Assert Assert.AreEqual(ex.InnerException, exception); }
public void VerifyPersistenceThrowsIfDataReadIsDiffrentFromDataWritten() { // Arrange var stringListener = new TraceStringListener(); var actualLogger = new TraceSourceLogger(_logger); var cacheAccessor = Substitute.For <ICacheAccessor>(); cacheAccessor.CreateForPersistenceValidation().Returns(cacheAccessor); var storage = new MsalCacheStorage(s_storageCreationProperties, cacheAccessor, actualLogger); cacheAccessor.Read().Returns(Encoding.UTF8.GetBytes("other_dummy_data")); // Act var ex = AssertException.Throws <MsalCachePersistenceException>( () => storage.VerifyPersistence()); // Assert Assert.IsNull(ex.InnerException); // no more details available }
/// <summary> /// Notification that is triggered before token acquisition. /// </summary> /// <param name="args">Arguments related to the cache item impacted</param> public override void BeforeAccessNotification(TokenCacheNotificationArgs args) { MsalCacheStorage cacheStorage = GetMsalCacheStorage(); args.AssertNotNull(nameof(args)); try { cacheLock = new CrossPlatformLock($"{CacheFilePath}.lockfile"); cacheLock.CreateLockAsync().ConfigureAwait(false); args.TokenCache.DeserializeMsalV3(cacheStorage.ReadData()); } catch (Exception) { cacheStorage.Clear(); throw; } }
internal SharedTokenCacheProvider(StorageCreationPropertiesBuilder builder, IConfiguration config = null, ILogger logger = null) { _logger = logger; _config = config ?? new ConfigurationBuilder().AddEnvironmentVariables().Build(); var authority = _config.GetValue <string>(Constants.AadAuthorityEnvName) ?? string.Format(CultureInfo.InvariantCulture, AadAuthority.AadCanonicalAuthorityTemplate, AadAuthority.DefaultTrustedHost, "common"); _app = PublicClientApplicationBuilder .Create(AzureCliClientId) .WithAuthority(new Uri(authority)) .Build(); var cacheStore = new MsalCacheStorage(builder.Build()); _cacheHelper = new MsalCacheHelper(_app.UserTokenCache, cacheStore); _cacheHelper.RegisterCache(_app.UserTokenCache); }
public void CacheStorageCanHandleMultipleExceptionsWhenReading() { // Arrange var stringListener = new TraceStringListener(); var cacheAccessor = Substitute.For <ICacheAccessor>(); var exception = new InvalidOperationException("some error"); cacheAccessor.Read().Throws(exception); cacheAccessor.When((x) => x.Clear()).Do(x => throw exception); _logger.Listeners.Add(stringListener); var actualLogger = new TraceSourceLogger(_logger); var storage = new MsalCacheStorage(s_storageCreationProperties, cacheAccessor, actualLogger); // Act byte[] result = storage.ReadData(); // Assert Assert.AreEqual(0, result.Length); Assert.IsTrue(stringListener.CurrentLog.Contains("TestSource Error")); Assert.IsTrue(stringListener.CurrentLog.Contains("InvalidOperationException")); Assert.IsTrue(stringListener.CurrentLog.Contains("some error")); }
public void ImportExport() { // Arrange var cacheAccessor = NSubstitute.Substitute.For <ICacheAccessor>(); var cache = new MockTokenCache(); var storage = new MsalCacheStorage( _storageCreationPropertiesBuilder.Build(), cacheAccessor, new TraceSourceLogger(new TraceSource("ts"))); var helper = new MsalCacheHelper(cache, storage, _logger); byte[] dataToSave = Encoding.UTF8.GetBytes("Hello World 2"); cacheAccessor.Read().Returns(Encoding.UTF8.GetBytes("Hello World")); // Act byte[] actualData = helper.LoadUnencryptedTokenCache(); helper.SaveUnencryptedTokenCache(dataToSave); // Assert Assert.AreEqual("Hello World", Encoding.UTF8.GetString(actualData)); cacheAccessor.Received().Write(dataToSave); }
public void VerifyPersistenceHappyPath() { // Arrange byte[] dummyData = Encoding.UTF8.GetBytes(MsalCacheStorage.PersistenceValidationDummyData); var actualLogger = new TraceSourceLogger(_logger); var cacheAccessor = Substitute.For <ICacheAccessor>(); cacheAccessor.CreateForPersistenceValidation().Returns(cacheAccessor); var storage = new MsalCacheStorage(s_storageCreationProperties, cacheAccessor, actualLogger); cacheAccessor.Read().Returns(dummyData); // Act storage.VerifyPersistence(); // Assert Received.InOrder(() => { cacheAccessor.CreateForPersistenceValidation(); cacheAccessor.Write(Arg.Any <byte[]>()); cacheAccessor.Read(); cacheAccessor.Clear(); }); }
public void MsalTestClear() { var store = MsalCacheStorage.Create(s_storageCreationProperties, logger: _logger); store.ReadData(); var store2 = MsalCacheStorage.Create(s_storageCreationProperties, logger: _logger); AssertException.Throws <ArgumentNullException>(() => store.WriteData(null)); byte[] data = { 2, 2, 3 }; store.WriteData(data); store2.ReadData(); Assert.IsTrue(Enumerable.SequenceEqual(store.ReadData(), data)); Assert.IsTrue(File.Exists(CacheFilePath)); store.Clear(); Assert.IsFalse(store.ReadData().Any()); Assert.IsFalse(store2.ReadData().Any()); Assert.IsFalse(File.Exists(CacheFilePath)); }
private void CleanTestData() { var store = MsalCacheStorage.Create(s_storageCreationProperties, logger: _logger); store.Clear(); }