diff --git a/Microsoft.Azure.Cosmos/src/Authorization/AuthorizationTokenProviderTokenCredential.cs b/Microsoft.Azure.Cosmos/src/Authorization/AuthorizationTokenProviderTokenCredential.cs index 4f81021f4b..ad9476c2aa 100644 --- a/Microsoft.Azure.Cosmos/src/Authorization/AuthorizationTokenProviderTokenCredential.cs +++ b/Microsoft.Azure.Cosmos/src/Authorization/AuthorizationTokenProviderTokenCredential.cs @@ -19,13 +19,13 @@ internal sealed class AuthorizationTokenProviderTokenCredential : AuthorizationT public AuthorizationTokenProviderTokenCredential( TokenCredential tokenCredential, - string accountEndpointHost, + Uri accountEndpoint, TimeSpan requestTimeout, TimeSpan? backgroundTokenCredentialRefreshInterval) { this.tokenCredentialCache = new TokenCredentialCache( tokenCredential: tokenCredential, - accountEndpointHost: accountEndpointHost, + accountEndpoint: accountEndpoint, requestTimeout: requestTimeout, backgroundTokenCredentialRefreshInterval: backgroundTokenCredentialRefreshInterval); } diff --git a/Microsoft.Azure.Cosmos/src/Authorization/TokenCredentialCache.cs b/Microsoft.Azure.Cosmos/src/Authorization/TokenCredentialCache.cs index ce8f3eb9fa..6becc003fd 100644 --- a/Microsoft.Azure.Cosmos/src/Authorization/TokenCredentialCache.cs +++ b/Microsoft.Azure.Cosmos/src/Authorization/TokenCredentialCache.cs @@ -50,14 +50,20 @@ internal sealed class TokenCredentialCache : IDisposable internal TokenCredentialCache( TokenCredential tokenCredential, - string accountEndpointHost, + Uri accountEndpoint, TimeSpan requestTimeout, TimeSpan? backgroundTokenCredentialRefreshInterval) { - this.tokenCredential = tokenCredential; + this.tokenCredential = tokenCredential ?? throw new ArgumentNullException(nameof(tokenCredential)); + + if (accountEndpoint == null) + { + throw new ArgumentNullException(nameof(accountEndpoint)); + } + this.tokenRequestContext = new TokenRequestContext(new string[] { - string.Format(TokenCredentialCache.ScopeFormat, accountEndpointHost) + string.Format(TokenCredentialCache.ScopeFormat, accountEndpoint.Host) }); if (requestTimeout <= TimeSpan.Zero) diff --git a/Microsoft.Azure.Cosmos/src/CosmosClient.cs b/Microsoft.Azure.Cosmos/src/CosmosClient.cs index 5cb4ae16a8..163c6f78cb 100644 --- a/Microsoft.Azure.Cosmos/src/CosmosClient.cs +++ b/Microsoft.Azure.Cosmos/src/CosmosClient.cs @@ -247,7 +247,7 @@ public CosmosClient( this.Endpoint = new Uri(accountEndpoint); this.AuthorizationTokenProvider = new AuthorizationTokenProviderTokenCredential( tokenCredential, - accountEndpoint, + this.Endpoint, clientOptions.RequestTimeout, clientOptions.TokenCredentialBackgroundRefreshInterval); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/LocalEmulatorTokenCredential.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/LocalEmulatorTokenCredential.cs index 75efbe51e5..2f1a17d687 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/LocalEmulatorTokenCredential.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/LocalEmulatorTokenCredential.cs @@ -5,11 +5,13 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests { using System; using System.Collections.Generic; + using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using global::Azure.Core; using IdentityModel.Tokens; + using Microsoft.VisualStudio.TestTools.UnitTesting; public class LocalEmulatorTokenCredential : TokenCredential { @@ -39,6 +41,9 @@ public override ValueTask GetTokenAsync(TokenRequestContext request private AccessToken GetAccessToken(TokenRequestContext requestContext, CancellationToken cancellationToken) { + // Verify that the request context is a valid URI + Assert.AreEqual("https://127.0.0.1/.default", requestContext.Scopes.First()); + this.GetTokenCallback?.Invoke( requestContext, cancellationToken); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosAuthorizationTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosAuthorizationTests.cs index 0cdce174c4..ec36b0a821 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosAuthorizationTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosAuthorizationTests.cs @@ -21,6 +21,12 @@ namespace Microsoft.Azure.Cosmos.Tests [TestClass] public class CosmosAuthorizationTests { + private static readonly Uri AccountEndpoint = new Uri("https://test-account.documents.azure.com"); + private const string ExpectedScope = "https://test-account.documents.azure.com/.default"; + + private readonly AccessToken AccessToken = new AccessToken("AccessToken", DateTimeOffset.MaxValue); + + public CosmosAuthorizationTests() { } @@ -79,7 +85,7 @@ public async Task TokenAuthAsync() using AuthorizationTokenProvider cosmosAuthorization = new AuthorizationTokenProviderTokenCredential( simpleEmulatorTokenCredential, - "https://localhost:8081", + new Uri("https://127.0.0.1:8081"), requestTimeout: TimeSpan.FromSeconds(30), backgroundTokenCredentialRefreshInterval: TimeSpan.FromSeconds(1)); @@ -137,7 +143,7 @@ public void TestTokenCredentialCacheMaxAndMinValues() TimeSpan toLarge = TimeSpan.MaxValue - TimeSpan.FromMilliseconds(1); new TokenCredentialCache( new Mock().Object, - CosmosAuthorizationTests.AccountEndpointHost, + CosmosAuthorizationTests.AccountEndpoint, requestTimeout: TimeSpan.FromSeconds(15), backgroundTokenCredentialRefreshInterval: toLarge); Assert.Fail("Should throw ArgumentException"); @@ -151,7 +157,7 @@ public void TestTokenCredentialCacheMaxAndMinValues() { new TokenCredentialCache( new Mock().Object, - CosmosAuthorizationTests.AccountEndpointHost, + CosmosAuthorizationTests.AccountEndpoint, requestTimeout: TimeSpan.FromSeconds(15), backgroundTokenCredentialRefreshInterval: TimeSpan.MinValue); Assert.Fail("Should throw ArgumentException"); @@ -165,7 +171,7 @@ public void TestTokenCredentialCacheMaxAndMinValues() { new TokenCredentialCache( new Mock().Object, - CosmosAuthorizationTests.AccountEndpointHost, + CosmosAuthorizationTests.AccountEndpoint, requestTimeout: TimeSpan.FromSeconds(15), backgroundTokenCredentialRefreshInterval: TimeSpan.Zero); Assert.Fail("Should throw ArgumentException"); @@ -179,7 +185,7 @@ public void TestTokenCredentialCacheMaxAndMinValues() { new TokenCredentialCache( new Mock().Object, - CosmosAuthorizationTests.AccountEndpointHost, + CosmosAuthorizationTests.AccountEndpoint, requestTimeout: TimeSpan.FromSeconds(15), backgroundTokenCredentialRefreshInterval: TimeSpan.FromMilliseconds(-1)); Assert.Fail("Should throw ArgumentException"); @@ -193,7 +199,7 @@ public void TestTokenCredentialCacheMaxAndMinValues() { new TokenCredentialCache( new Mock().Object, - CosmosAuthorizationTests.AccountEndpointHost, + CosmosAuthorizationTests.AccountEndpoint, requestTimeout: TimeSpan.MinValue, backgroundTokenCredentialRefreshInterval: TimeSpan.FromMinutes(1)); Assert.Fail("Should throw ArgumentException"); @@ -207,7 +213,7 @@ public void TestTokenCredentialCacheMaxAndMinValues() { new TokenCredentialCache( new Mock().Object, - CosmosAuthorizationTests.AccountEndpointHost, + CosmosAuthorizationTests.AccountEndpoint, requestTimeout: TimeSpan.Zero, backgroundTokenCredentialRefreshInterval: TimeSpan.FromMinutes(1)); Assert.Fail("Should throw ArgumentException"); @@ -220,22 +226,17 @@ public void TestTokenCredentialCacheMaxAndMinValues() // Which is roughly 24 days using TokenCredentialCache token = new TokenCredentialCache( new Mock().Object, - CosmosAuthorizationTests.AccountEndpointHost, + CosmosAuthorizationTests.AccountEndpoint, requestTimeout: TimeSpan.FromSeconds(15), backgroundTokenCredentialRefreshInterval: TimeSpan.FromMilliseconds(Int32.MaxValue)); using TokenCredentialCache disableBackgroundTask = new TokenCredentialCache( new Mock().Object, - CosmosAuthorizationTests.AccountEndpointHost, + CosmosAuthorizationTests.AccountEndpoint, requestTimeout: TimeSpan.FromSeconds(15), backgroundTokenCredentialRefreshInterval: TimeSpan.MaxValue); } - private const string AccountEndpointHost = "test-account.documents.azure.com"; - private const string ExpectedScope = "https://test-account.documents.azure.com/.default"; - - private readonly AccessToken AccessToken = new AccessToken("AccessToken", DateTimeOffset.MaxValue); - [TestMethod] public async Task TestTokenCredentialCacheHappyPathAsync() { @@ -440,7 +441,7 @@ private TokenCredentialCache CreateTokenCredentialCache( { return new TokenCredentialCache( tokenCredential, - CosmosAuthorizationTests.AccountEndpointHost, + CosmosAuthorizationTests.AccountEndpoint, requestTimeout: requestTimeout ?? TimeSpan.FromSeconds(15), backgroundTokenCredentialRefreshInterval: TimeSpan.FromSeconds(5)); }