public async Task GetTokenAsyncRespectsExpirationBufferForJwtTokens()
        {
            var tokenValue     = "ValuE_oF_tHE_tokEn";
            var buffer         = TimeSpan.FromMinutes(5);
            var expires        = DateTimeOffset.UtcNow.Subtract(buffer).AddSeconds(-10);
            var mockCredential = new Mock <TokenCredential>();
            var credential     = new ServiceBusTokenCredential(mockCredential.Object);

            using var provider = new CbsTokenProvider(credential, TimeSpan.Zero, default);

            mockCredential
            .Setup(credential => credential.GetTokenAsync(It.IsAny <TokenRequestContext>(), It.IsAny <CancellationToken>()))
            .Returns(new ValueTask <AccessToken>(new AccessToken(tokenValue, expires)));

            var firstCallToken = await provider.GetTokenAsync(new Uri("http://www.here.com"), "nobody", new string[0]);

            var nextCallToken = await provider.GetTokenAsync(new Uri("http://www.here.com"), "nobody", new string[0]);

            Assert.That(firstCallToken, Is.Not.Null, "The first call token should have been produced.");
            Assert.That(nextCallToken, Is.Not.Null, "The next call token should have been produced.");
            Assert.That(firstCallToken, Is.Not.SameAs(nextCallToken), "The token should have been expired and returned two unique instances.");

            mockCredential
            .Verify(credential => credential.GetTokenAsync(
                        It.IsAny <TokenRequestContext>(),
                        It.IsAny <CancellationToken>()),
                    Times.Exactly(2));
        }
        public async Task GetTokenAsyncRespectsCacheForJwtTokens()
        {
            var tokenValue     = "ValuE_oF_tHE_tokEn";
            var expires        = DateTimeOffset.UtcNow.AddDays(1);
            var mockCredential = new Mock <TokenCredential>();
            var credential     = new ServiceBusTokenCredential(mockCredential.Object);

            using var provider = new CbsTokenProvider(credential, TimeSpan.Zero, default);

            mockCredential
            .Setup(credential => credential.GetTokenAsync(It.IsAny <TokenRequestContext>(), It.IsAny <CancellationToken>()))
            .Returns(new ValueTask <AccessToken>(new AccessToken(tokenValue, expires)));

            var firstCallToken = await provider.GetTokenAsync(new Uri("http://www.here.com"), "nobody", new string[0]);

            var nextCallToken = await provider.GetTokenAsync(new Uri("http://www.here.com"), "nobody", new string[0]);

            Assert.That(firstCallToken, Is.Not.Null, "The first call token should have been produced.");
            Assert.That(nextCallToken, Is.Not.Null, "The next call token should have been produced.");
            Assert.That(firstCallToken, Is.SameAs(nextCallToken), "The same token instance should have been returned for both calls.");

            mockCredential
            .Verify(credential => credential.GetTokenAsync(
                        It.IsAny <TokenRequestContext>(),
                        It.IsAny <CancellationToken>()),
                    Times.Once);
        }
        public async Task GetTokenAsyncDoesNotCacheSharedAccessCredential()
        {
            var value          = "TOkEn!";
            var signature      = new SharedAccessSignature("hub-name", "keyName", "key", value, DateTimeOffset.UtcNow.AddHours(4));
            var mockCredential = new Mock <SharedAccessCredential>(signature)
            {
                CallBase = true
            };
            var credential = new ServiceBusTokenCredential(mockCredential.Object);

            using var provider = new CbsTokenProvider(credential, TimeSpan.Zero, default);

            var firstCallToken = await provider.GetTokenAsync(new Uri("http://www.here.com"), "nobody", new string[0]);

            var nextCallToken = await provider.GetTokenAsync(new Uri("http://www.here.com"), "nobody", new string[0]);

            Assert.That(firstCallToken, Is.Not.Null, "The first call token should have been produced.");
            Assert.That(nextCallToken, Is.Not.Null, "The next call token should have been produced.");
            Assert.That(firstCallToken, Is.Not.SameAs(nextCallToken), "The token should have been expired and returned two unique instances.");

            mockCredential
            .Verify(credential => credential.GetTokenAsync(
                        It.IsAny <TokenRequestContext>(),
                        It.IsAny <CancellationToken>()),
                    Times.Exactly(2));
        }
        public async Task GetTokenAsyncSynchonizesMultipleRefreshAttemptsForJwtTokens()
        {
            var tokenValue     = "ValuE_oF_tHE_tokEn";
            var buffer         = TimeSpan.FromMinutes(5);
            var expires        = DateTimeOffset.UtcNow.Subtract(buffer).AddSeconds(-10);
            var mockCredential = new Mock <TokenCredential>();
            var credential     = new ServiceBusTokenCredential(mockCredential.Object);

            using var provider = new CbsTokenProvider(credential, TimeSpan.Zero, default);

            mockCredential
            .SetupSequence(credential => credential.GetTokenAsync(It.IsAny <TokenRequestContext>(), It.IsAny <CancellationToken>()))
            .Returns(new ValueTask <AccessToken>(new AccessToken(tokenValue, expires)))
            .Returns(new ValueTask <AccessToken>(new AccessToken(tokenValue, DateTimeOffset.UtcNow.AddDays(1))));

            var firstCallToken = await provider.GetTokenAsync(new Uri("http://www.here.com"), "nobody", new string[0]);

            Assert.That(firstCallToken, Is.Not.Null, "The first call token should have been produced.");

            var otherTokens = await Task.WhenAll(
                Enumerable.Range(0, 25)
                .Select(index => provider.GetTokenAsync(new Uri("http://www.here.com"), "nobody", new string[0])));

            for (var index = 0; index < otherTokens.Length; ++index)
            {
                Assert.That(otherTokens[index], Is.Not.Null, $"The token at index `{ index }` should have been produced.");
                Assert.That(firstCallToken, Is.Not.SameAs(otherTokens[index]), $"The token at index `{ index } ` should not have matched the first call instance.");

                if (index > 0)
                {
                    Assert.That(otherTokens[0], Is.SameAs(otherTokens[index]), $"The other tokens should all be the same instance.  The token at index `{ index } ` did not match index `0`.");
                }
            }

            mockCredential
            .Verify(credential => credential.GetTokenAsync(
                        It.IsAny <TokenRequestContext>(),
                        It.IsAny <CancellationToken>()),
                    Times.Exactly(2));
        }
        public async Task GetTokenAsyncDelegatesToTheSourceCredential()
        {
            var mockCredential = new Mock <TokenCredential>();
            var accessToken    = new AccessToken("token", new DateTimeOffset(2015, 10, 27, 12, 0, 0, TimeSpan.Zero));
            var resource       = "the resource value";
            var credential     = new ServiceBusTokenCredential(mockCredential.Object);

            mockCredential
            .Setup(cred => cred.GetTokenAsync(It.Is <TokenRequestContext>(value => value.Scopes.FirstOrDefault() == resource), It.IsAny <CancellationToken>()))
            .ReturnsAsync(accessToken)
            .Verifiable("The source credential GetToken method should have been called.");

            AccessToken tokenResult = await credential.GetTokenAsync(new TokenRequestContext(new[] { resource }), CancellationToken.None);

            Assert.That(tokenResult, Is.EqualTo(accessToken), "The access token should match the return of the delegated call.");
            mockCredential.VerifyAll();
        }
        public async Task GetTokenAsyncSetsTheCorrectTypeForOtherTokens()
        {
            var tokenValue     = "ValuE_oF_tHE_tokEn";
            var expires        = DateTimeOffset.Parse("2015-10-27T00:00:00Z");
            var mockCredential = new Mock <TokenCredential>();
            var credential     = new ServiceBusTokenCredential(mockCredential.Object);

            using var provider = new CbsTokenProvider(credential, TimeSpan.Zero, default);

            mockCredential
            .Setup(credential => credential.GetTokenAsync(It.IsAny <TokenRequestContext>(), It.IsAny <CancellationToken>()))
            .Returns(new ValueTask <AccessToken>(new AccessToken(tokenValue, expires)));

            var cbsToken = await provider.GetTokenAsync(new Uri("http://www.here.com"), "nobody", new string[0]);

            Assert.That(cbsToken, Is.Not.Null, "The token should have been produced");
            Assert.That(cbsToken.TokenType, Is.EqualTo(GetGenericTokenType()), "The token type should match");
        }