From 5f15e89ee374be75ef3d5d544abe3c64eca2745b Mon Sep 17 00:00:00 2001 From: Christopher Scott Date: Fri, 8 Nov 2024 14:17:39 -0600 Subject: [PATCH 1/2] Fix ArgumentOutOfRangeException when token has default ExpiresOn value --- sdk/core/Azure.Core/CHANGELOG.md | 2 ++ .../BearerTokenAuthenticationPolicy.cs | 9 ++++++- .../BearerTokenAuthenticationPolicyTests.cs | 24 +++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/sdk/core/Azure.Core/CHANGELOG.md b/sdk/core/Azure.Core/CHANGELOG.md index 90f2f9fec090..4ec8cfc5e9f0 100644 --- a/sdk/core/Azure.Core/CHANGELOG.md +++ b/sdk/core/Azure.Core/CHANGELOG.md @@ -8,6 +8,8 @@ ### Bugs Fixed +- Fixed an issue where `BearerTokenAuthenticationPolicy` throws `ArgumentOutOfRangeException` if the `ExpiresOn` property of the token is the default value. ([#]()) + ### Other Changes - Use `BinaryData.Empty` for `PipelineResponse.Content` when HTTP message has no content. diff --git a/sdk/core/Azure.Core/src/Pipeline/BearerTokenAuthenticationPolicy.cs b/sdk/core/Azure.Core/src/Pipeline/BearerTokenAuthenticationPolicy.cs index 83a8f5aca873..c13b7bc7666f 100644 --- a/sdk/core/Azure.Core/src/Pipeline/BearerTokenAuthenticationPolicy.cs +++ b/sdk/core/Azure.Core/src/Pipeline/BearerTokenAuthenticationPolicy.cs @@ -395,7 +395,14 @@ private async ValueTask SetResultOnTcsFromCredentialAsync(TokenRequestContext co ? await _credential.GetTokenAsync(context, cancellationToken).ConfigureAwait(false) : _credential.GetToken(context, cancellationToken); - targetTcs.SetResult(new AuthHeaderValueInfo("Bearer " + token.Token, token.ExpiresOn, token.RefreshOn.HasValue ? token.RefreshOn.Value : token.ExpiresOn - _tokenRefreshOffset)); + DateTimeOffset refreshOn = token.RefreshOn.HasValue switch + { + true => token.RefreshOn.Value, + false when _tokenRefreshOffset.Ticks > token.ExpiresOn.Ticks => token.ExpiresOn, + _ => token.ExpiresOn - _tokenRefreshOffset + }; + + targetTcs.SetResult(new AuthHeaderValueInfo("Bearer " + token.Token, token.ExpiresOn, refreshOn)); } internal readonly struct AuthHeaderValueInfo diff --git a/sdk/core/Azure.Core/tests/BearerTokenAuthenticationPolicyTests.cs b/sdk/core/Azure.Core/tests/BearerTokenAuthenticationPolicyTests.cs index 7597391db2ec..e132d3b3a576 100644 --- a/sdk/core/Azure.Core/tests/BearerTokenAuthenticationPolicyTests.cs +++ b/sdk/core/Azure.Core/tests/BearerTokenAuthenticationPolicyTests.cs @@ -57,6 +57,30 @@ public async Task BearerTokenAuthenticationPolicy_RequestsTokenEveryRequest() Assert.AreEqual("Bearer token2", auth2Value); } + [Test] + public async Task BearerTokenAuthenticationPolicy_RequestsTokenEveryRequest_InvalidExpiresOn() + { + var accessTokens = new Queue(); + accessTokens.Enqueue(new AccessToken("token1", default)); + accessTokens.Enqueue(new AccessToken("token2", default)); + + var credential = new TokenCredentialStub( + (r, c) => r.Scopes.SequenceEqual(new[] { "scope1", "scope2" }) ? accessTokens.Dequeue() : default, + IsAsync); + + var policy = new BearerTokenAuthenticationPolicy(credential, new[] { "scope1", "scope2" }); + MockTransport transport = CreateMockTransport(new MockResponse(200), new MockResponse(200)); + + await SendGetRequest(transport, policy, uri: new Uri("https://example.com")); + await SendGetRequest(transport, policy, uri: new Uri("https://example.com")); + + Assert.True(transport.Requests[0].Headers.TryGetValue("Authorization", out string auth1Value)); + Assert.True(transport.Requests[1].Headers.TryGetValue("Authorization", out string auth2Value)); + + Assert.AreEqual("Bearer token1", auth1Value); + Assert.AreEqual("Bearer token2", auth2Value); + } + [Test] public async Task BearerTokenAuthenticationPolicy_CachesHeaderValue() { From 3b1ae8ba9b773dc8aacb13861bd78c73d7cdb613 Mon Sep 17 00:00:00 2001 From: Christopher Scott Date: Fri, 8 Nov 2024 14:18:37 -0600 Subject: [PATCH 2/2] changelog --- sdk/core/Azure.Core/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/core/Azure.Core/CHANGELOG.md b/sdk/core/Azure.Core/CHANGELOG.md index 4ec8cfc5e9f0..554453bc8721 100644 --- a/sdk/core/Azure.Core/CHANGELOG.md +++ b/sdk/core/Azure.Core/CHANGELOG.md @@ -8,7 +8,7 @@ ### Bugs Fixed -- Fixed an issue where `BearerTokenAuthenticationPolicy` throws `ArgumentOutOfRangeException` if the `ExpiresOn` property of the token is the default value. ([#]()) +- Fixed an issue where `BearerTokenAuthenticationPolicy` throws `ArgumentOutOfRangeException` if the `ExpiresOn` property of the token is the default value. ([#47040](https://github.com/Azure/azure-sdk-for-net/pull/47040)) ### Other Changes