Skip to content

Commit bd68205

Browse files
authored
Fix ArgumentOutOfRangeException when token has default ExpiresOn value (#47040)
1 parent d9e0d05 commit bd68205

File tree

3 files changed

+34
-1
lines changed

3 files changed

+34
-1
lines changed

sdk/core/Azure.Core/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
### Bugs Fixed
1010

11+
- 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))
12+
1113
### Other Changes
1214

1315
- Use `BinaryData.Empty` for `PipelineResponse.Content` when HTTP message has no content.

sdk/core/Azure.Core/src/Pipeline/BearerTokenAuthenticationPolicy.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,14 @@ private async ValueTask SetResultOnTcsFromCredentialAsync(TokenRequestContext co
395395
? await _credential.GetTokenAsync(context, cancellationToken).ConfigureAwait(false)
396396
: _credential.GetToken(context, cancellationToken);
397397

398-
targetTcs.SetResult(new AuthHeaderValueInfo("Bearer " + token.Token, token.ExpiresOn, token.RefreshOn.HasValue ? token.RefreshOn.Value : token.ExpiresOn - _tokenRefreshOffset));
398+
DateTimeOffset refreshOn = token.RefreshOn.HasValue switch
399+
{
400+
true => token.RefreshOn.Value,
401+
false when _tokenRefreshOffset.Ticks > token.ExpiresOn.Ticks => token.ExpiresOn,
402+
_ => token.ExpiresOn - _tokenRefreshOffset
403+
};
404+
405+
targetTcs.SetResult(new AuthHeaderValueInfo("Bearer " + token.Token, token.ExpiresOn, refreshOn));
399406
}
400407

401408
internal readonly struct AuthHeaderValueInfo

sdk/core/Azure.Core/tests/BearerTokenAuthenticationPolicyTests.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,30 @@ public async Task BearerTokenAuthenticationPolicy_RequestsTokenEveryRequest()
5757
Assert.AreEqual("Bearer token2", auth2Value);
5858
}
5959

60+
[Test]
61+
public async Task BearerTokenAuthenticationPolicy_RequestsTokenEveryRequest_InvalidExpiresOn()
62+
{
63+
var accessTokens = new Queue<AccessToken>();
64+
accessTokens.Enqueue(new AccessToken("token1", default));
65+
accessTokens.Enqueue(new AccessToken("token2", default));
66+
67+
var credential = new TokenCredentialStub(
68+
(r, c) => r.Scopes.SequenceEqual(new[] { "scope1", "scope2" }) ? accessTokens.Dequeue() : default,
69+
IsAsync);
70+
71+
var policy = new BearerTokenAuthenticationPolicy(credential, new[] { "scope1", "scope2" });
72+
MockTransport transport = CreateMockTransport(new MockResponse(200), new MockResponse(200));
73+
74+
await SendGetRequest(transport, policy, uri: new Uri("https://example.com"));
75+
await SendGetRequest(transport, policy, uri: new Uri("https://example.com"));
76+
77+
Assert.True(transport.Requests[0].Headers.TryGetValue("Authorization", out string auth1Value));
78+
Assert.True(transport.Requests[1].Headers.TryGetValue("Authorization", out string auth2Value));
79+
80+
Assert.AreEqual("Bearer token1", auth1Value);
81+
Assert.AreEqual("Bearer token2", auth2Value);
82+
}
83+
6084
[Test]
6185
public async Task BearerTokenAuthenticationPolicy_CachesHeaderValue()
6286
{

0 commit comments

Comments
 (0)