Azure / azure-sdk-for-net

This repository is for active development of the Azure SDK for .NET. For consumers of the SDK we recommend visiting our public developer docs at https://learn.microsoft.com/dotnet/azure/ or our versioned developer docs at https://azure.github.io/azure-sdk-for-net.
MIT License
5.47k stars 4.8k forks source link

[BUG] BearerTokenAuthenticationPolicy throws ArgumentOutOfRangeException: The added or subtracted value results in an un-representable DateTime. #47002

Closed tomkerkhove closed 1 day ago

tomkerkhove commented 6 days ago

Library name and version

Azure.Core 1.42.0

Describe the bug

Using Azure.Messaging.EventGrid (4.24.0) to publish events which often fails due to BearerTokenAuthenticationPolicy throwing ArgumentOutOfRangeException (see below)

Expected behavior

Events to successfully emit to topic.

Actual behavior

Exception thrown:

System.ArgumentOutOfRangeException: The added or subtracted value results in an un-representable DateTime.
Parameter name: t
   at System.DateTime.op_Subtraction(DateTime d, TimeSpan t)
   at System.DateTimeOffset.op_Subtraction(DateTimeOffset dateTimeOffset, TimeSpan timeSpan)
   at Azure.Core.Pipeline.BearerTokenAuthenticationPolicy.AccessTokenCache.<SetResultOnTcsFromCredentialAsync>d__9.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Azure.Core.Pipeline.BearerTokenAuthenticationPolicy.AccessTokenCache.<GetAuthHeaderValueAsync>d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Azure.Core.Pipeline.BearerTokenAuthenticationPolicy.AccessTokenCache.TokenRequestState.<GetCurrentHeaderValue>d__19.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Azure.Core.Pipeline.BearerTokenAuthenticationPolicy.AccessTokenCache.<GetAuthHeaderValueAsync>d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Azure.Core.Pipeline.BearerTokenAuthenticationPolicy.<AuthenticateAndAuthorizeRequestAsync>d__12.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Azure.Core.Pipeline.BearerTokenAuthenticationPolicy.<ProcessAsync>d__11.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Azure.Core.Pipeline.RedirectPolicy.<ProcessAsync>d__7.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Azure.Core.Pipeline.RetryPolicy.<ProcessAsync>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Azure.Core.Pipeline.RetryPolicy.<ProcessAsync>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Azure.Messaging.EventGrid.EventGridPublisherClient.<SendEventsInternal>d__15.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Azure.Messaging.EventGrid.EventGridPublisherClient.<SendEventsAsync>d__13.MoveNext()

Reproduction Steps

Not sure when this happens, likely after token expires or need new one here:

Environment

No response

tomkerkhove commented 6 days ago

https://github.com/Azure/azure-sdk-for-net/blob/d96e4ea52f6078e6e09d7933c6281ff94880d435/sdk/core/Azure.Core/src/Pipeline/BearerTokenAuthenticationPolicy.cs#L398C154-L398C191 is likely culprit where token.ExpiresOn can be null

jsquire commented 6 days ago

@christothes: Would you please take a look and offer your thoughts?

christothes commented 6 days ago

Hi @tomkerkhove - I'm curious under which conditions the token contains a null ExpiresOn value. We can certainly protect against throwing here, but this seems like an unexpected situation. Which credential type are you using?

tomkerkhove commented 6 days ago

Given we can use ITokenProvider, anyone can give a default(AccessToken) or similar

christothes commented 5 days ago

Given we can use ITokenProvider, anyone can give a default(AccessToken) or similar

Do you have any ideas as to how this would be happening in your scenario?

tomkerkhove commented 5 days ago

I'd say when there is a bug, or when token could not be retried which would make it the default value

christothes commented 1 day ago

Fixed in https://github.com/Azure/azure-sdk-for-net/pull/47040

tomkerkhove commented 1 day ago

Thank you!