public void TestDeserializeWithClearCache()
        {
            // Create a token accessor with keys in it that are NOT in the expected token cache
            var originalAccessor = CreateTokenCacheAccessorWithKeyPrefix("FAKE", 7, 6, 5, 4);
            var s1 = new TokenCacheJsonSerializer(originalAccessor);

            byte[] originalBytes = s1.Serialize(null);

            var differentAccessor = CreateTokenCacheAccessor();
            var s2 = new TokenCacheJsonSerializer(differentAccessor);

            byte[] differentBytes = s2.Serialize(null);

            // Assert that they have different counts of items...
            Assert.AreNotEqual(originalAccessor.GetAllAccessTokens().Count(), differentAccessor.GetAllAccessTokens().Count());
            Assert.AreNotEqual(originalAccessor.GetAllRefreshTokens().Count(), differentAccessor.GetAllRefreshTokens().Count());
            Assert.AreNotEqual(originalAccessor.GetAllIdTokens().Count(), differentAccessor.GetAllIdTokens().Count());
            Assert.AreNotEqual(originalAccessor.GetAllAccounts().Count(), differentAccessor.GetAllAccounts().Count());

            // Now, deserialize differentBytes into originalAccessor with cacheFlush = true
            // This means we should destroy the contents of originalAccessor and replace them with the
            // contents of the different cache

            s1.Deserialize(differentBytes, true);

            AssertAccessorsAreEqual(differentAccessor, originalAccessor);

            string expectedJson = File.ReadAllText(ResourceHelper.GetTestResourceRelativePath("ExpectedTokenCache.json"));

            // serialize again to detect errors that come from deserialization
            byte[] bytes2      = s1.Serialize(null);
            string actualJson2 = new UTF8Encoding().GetString(bytes2);

            Assert.IsTrue(JToken.DeepEquals(JObject.Parse(actualJson2), JObject.Parse(expectedJson)));
        }
        public void TestJsonSerialization()
        {
            string expectedJson = File.ReadAllText(ResourceHelper.GetTestResourceRelativePath("ExpectedTokenCache.json"));
            var    accessor     = CreateTokenCacheAccessor();

            var s1 = new TokenCacheJsonSerializer(accessor);

            byte[] bytes      = s1.Serialize(null);
            string actualJson = new UTF8Encoding().GetString(bytes);

            Assert.IsTrue(JToken.DeepEquals(JObject.Parse(actualJson), JObject.Parse(expectedJson)));

            var otherAccessor = new InMemoryTokenCacheAccessor(Substitute.For <ICoreLogger>());
            var s2            = new TokenCacheJsonSerializer(otherAccessor);

            s2.Deserialize(bytes, false);

            AssertAccessorsAreEqual(accessor, otherAccessor);

            // serialize again to detect errors that come from deserialization
            byte[] bytes2      = s2.Serialize(null);
            string actualJson2 = new UTF8Encoding().GetString(bytes2);

            Assert.IsTrue(JToken.DeepEquals(JObject.Parse(actualJson2), JObject.Parse(expectedJson)));
        }
Exemple #3
0
        internal static void PopulateDefaultAppTokenCache(
            ConfidentialClientApplication app,
            MsalAccessTokenCacheItem atItem = null)
        {
            if (atItem == null)
            {
                atItem = CreateAccessTokenItem();
            }

            InMemoryTokenCacheAccessor accessor = new InMemoryTokenCacheAccessor(new NullLogger());

            accessor.SaveAccessToken(atItem);

            string key = SuggestedWebCacheKeyFactory.GetClientCredentialKey(atItem.ClientId, atItem.TenantId);

            byte[] bytes = new TokenCacheJsonSerializer(accessor).Serialize(null);
            app.InMemoryPartitionedCacheSerializer.CachePartition[key] = bytes;

            // force a cache read
            var args = new TokenCacheNotificationArgs(
                app.AppTokenCacheInternal,
                app.AppConfig.ClientId,
                null,
                hasStateChanged: false,
                true,
                hasTokens: true,
                suggestedCacheKey: key);

            app.AppTokenCacheInternal.OnBeforeAccessAsync(args).GetAwaiter().GetResult();
        }
        public void TestPythonCacheSerializationInterop()
        {
            var    accessor          = new InMemoryTokenCacheAccessor(Substitute.For <ICoreLogger>());
            var    s                 = new TokenCacheJsonSerializer(accessor);
            string pythonBinFilePath = ResourceHelper.GetTestResourceRelativePath("cachecompat_python.bin");

            byte[] bytes = File.ReadAllBytes(pythonBinFilePath);
            s.Deserialize(bytes, false);

            Assert.AreEqual(0, accessor.GetAllAccessTokens().Count());
            Assert.AreEqual(0, accessor.GetAllRefreshTokens().Count());
            Assert.AreEqual(0, accessor.GetAllIdTokens().Count());
            Assert.AreEqual(0, accessor.GetAllAccounts().Count());
        }
        public void TestSerializeContainsNoNulls()
        {
            var accessor = CreateTokenCacheAccessor();

            // Create a refresh token with a null family id in it
            var item = CreateRefreshTokenItem();

            item.FamilyId    = null;
            item.Environment = item.Environment + $"_SOMERANDOMPREFIX"; // ensure we get unique cache keys
            accessor.SaveRefreshToken(item);

            var s1 = new TokenCacheJsonSerializer(accessor);

            byte[] bytes = s1.Serialize(null);
            string json  = CoreHelpers.ByteArrayToString(bytes);

            Console.WriteLine(json);
            Assert.IsFalse(json.ToLowerInvariant().Contains("null"));
        }
        public void TestDeserializeWithNoClearCache()
        {
            // Create a token accessor with keys in it that are NOT in the expected token cache
            var originalAccessor = CreateTokenCacheAccessorWithKeyPrefix("FAKE", 7, 6, 5, 4);
            var s1 = new TokenCacheJsonSerializer(originalAccessor);

            byte[] originalBytes = s1.Serialize(null);

            var differentAccessor = CreateTokenCacheAccessor();
            var s2 = new TokenCacheJsonSerializer(differentAccessor);

            byte[] differentBytes = s2.Serialize(null);

            // Assert that they have different counts of items...

            int originalAccessTokenCount  = originalAccessor.GetAllAccessTokens().Count();
            int originalRefreshTokenCount = originalAccessor.GetAllRefreshTokens().Count();
            int originalIdTokenCount      = originalAccessor.GetAllIdTokens().Count();
            int originalAccountsCount     = originalAccessor.GetAllAccounts().Count();

            Assert.AreNotEqual(originalAccessTokenCount, differentAccessor.GetAllAccessTokens().Count());
            Assert.AreNotEqual(originalRefreshTokenCount, differentAccessor.GetAllRefreshTokens().Count());
            Assert.AreNotEqual(originalIdTokenCount, differentAccessor.GetAllIdTokens().Count());
            Assert.AreNotEqual(originalAccountsCount, differentAccessor.GetAllAccounts().Count());

            // Now, deserialize differentBytes into originalAccessor with cacheFlush = false
            // This means we should merge the contents of originalAccessor and the
            // contents of the different cache

            s1.Deserialize(differentBytes, false);

            Assert.AreEqual(originalAccessor.GetAllAccessTokens().Count(), differentAccessor.GetAllAccessTokens().Count() + originalAccessTokenCount);

            // This is -1 because the PRT FOCI refresh token will not duplicate since it has the same key.
            Assert.AreEqual(originalAccessor.GetAllRefreshTokens().Count(), differentAccessor.GetAllRefreshTokens().Count() + originalRefreshTokenCount - 1);
            Assert.AreEqual(originalAccessor.GetAllIdTokens().Count(), differentAccessor.GetAllIdTokens().Count() + originalIdTokenCount);
            Assert.AreEqual(originalAccessor.GetAllAccounts().Count(), differentAccessor.GetAllAccounts().Count() + originalAccountsCount);
        }
        private void PopulateAppCache(ConfidentialClientApplication cca, TokenDifference tokenDifference, int size)
        {
            Dictionary <string, InMemoryTokenCacheAccessor> accessors = new Dictionary <string, InMemoryTokenCacheAccessor>();
            string key = "";

            for (int i = 0; i < size; i++)
            {
                string tenantId = "tid";
                string scope    = "scope";

                switch (tokenDifference)
                {
                case TokenDifference.ByScope:
                    scope = $"scope_{i}";
                    break;

                case TokenDifference.ByTenant:
                    tenantId = $"tid_{i}";
                    break;

                default:
                    throw new NotImplementedException();
                }

                MsalAccessTokenCacheItem atItem = new MsalAccessTokenCacheItem(
                    TestConstants.ProductionPrefCacheEnvironment,
                    TestConstants.ClientId,
                    scope,
                    tenantId,
                    "",
                    new DateTimeOffset(DateTime.UtcNow + TimeSpan.FromSeconds(3600)),
                    new DateTimeOffset(DateTime.UtcNow + TimeSpan.FromSeconds(3600)),
                    null,
                    null);

                key = SuggestedWebCacheKeyFactory.GetClientCredentialKey(atItem.ClientId, atItem.TenantId);
                InMemoryTokenCacheAccessor accessor;
                if (!accessors.TryGetValue(key, out accessor))
                {
                    accessor       = new InMemoryTokenCacheAccessor(new NullLogger());
                    accessors[key] = accessor;
                }

                accessor.SaveAccessToken(atItem);

                if (tokenDifference == TokenDifference.ByTenant || (tokenDifference == TokenDifference.ByScope && i == size - 1))
                {
                    byte[] bytes = new TokenCacheJsonSerializer(accessor).Serialize(null);
                    cca.InMemoryPartitionedCacheSerializer.CachePartition[key] = bytes;
                }
            }

            // force a cache read, otherwise MSAL won't have the tokens in memory
            // force a cache read
            var args = new TokenCacheNotificationArgs(
                cca.AppTokenCacheInternal,
                cca.AppConfig.ClientId,
                null,
                hasStateChanged: false,
                true,
                hasTokens: true,
                cancellationToken: CancellationToken.None,
                suggestedCacheKey: key);

            cca.AppTokenCacheInternal.OnBeforeAccessAsync(args).GetAwaiter().GetResult();
        }