-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[FEATURE REQ]Azure.Identity should handle token caching and refreshing when calling .GetTokenAsync just like AppAuthentication does #20011
Comments
Thank you for your feedback. Tagging and routing to the team best able to assist. |
Uhm. There's caching but it's slow. The I wrote this simple in-memory cache which takes less than 10 microseconds as long as the token is valid. The problem though is that the token I get back (from the So if the token I currently have these two issues:
I need this because I have to set the access token on the SqlConnection instance when the DataContext is created, there isn't a pull based API that can be used to pull in an access token when needed by the DataContext. I can ensure that all "unit of work" patterns that we have complete within 10 minutes but I cannot currently ensure that I get back a token which has at least 10 minutes of validity from the I need a way to express that the token I get back has the maximum allowed life-time of so that I can have a fast in-memory cache with some tolerance. And yes, this is because there's no way for the Entity Framework stuff to pull in the access token when needed, we have to put it in place before hand. And if the DataContext linger for more than a couple of minutes (which can happen in background jobs) we'll get a connection error because the access token will have expired. Also, I cannot find any documentation on what you might expect on the expiry. If the expiry is with some tolerance already. If so, that would be great but where is this documented!? Here's my simple in-memory cache. It cannot be used with a tolerance, i.e. class TokenRequestContextEqualityComparer : IEqualityComparer<TokenRequestContext>
{
static readonly string[] Empty = new string[] { };
public bool Equals(TokenRequestContext x, TokenRequestContext y)
{
var a = x.Scopes ?? Empty;
var b = y.Scopes ?? Empty;
if (a.Length != b.Length)
{
return false;
}
for (int i = 0; i < a.Length; i++)
{
if (a[i] != b[i])
{
return false;
}
}
return true;
}
public int GetHashCode(TokenRequestContext obj)
{
var scopes = obj.Scopes ?? Empty;
int hashCode = 0;
for (int i = 0; i < scopes.Length; i++)
{
hashCode ^= scopes[i].GetHashCode();
}
return hashCode;
}
}
class CachedAzureCredential : DefaultAzureCredential
{
private readonly ConcurrentDictionary<TokenRequestContext, AccessToken> _cache = new ConcurrentDictionary<TokenRequestContext, AccessToken>(new TokenRequestContextEqualityComparer());
public override AccessToken GetToken(TokenRequestContext requestContext, CancellationToken cancellationToken = default)
{
AccessToken cached;
if (_cache.TryGetValue(requestContext, out cached) && DateTimeOffset.UtcNow.AddMinutes(15) < cached.ExpiresOn)
{
return cached;
}
var accessToken = base.GetToken(requestContext, cancellationToken);
_cache[requestContext] = accessToken;
return accessToken;
}
public override async ValueTask<AccessToken> GetTokenAsync(TokenRequestContext requestContext, CancellationToken cancellationToken = default)
{
AccessToken cached;
if (_cache.TryGetValue(requestContext, out cached) && DateTimeOffset.UtcNow.AddMinutes(15) < cached.ExpiresOn)
{
return cached;
}
var accessToken = await base.GetTokenAsync(requestContext, cancellationToken);
_cache[requestContext] = accessToken;
return accessToken;
}
} |
@leidegre For EF, My issue is with the fact that the old I have not used |
I'm currently not on .NET Core, is there anything similar to the I don't use refresh tokens but the code I've provided will help with the token acquisition. |
@leidegre Sorry I started with EF Core and never used EF6, but it does appear to have Yeah I know a simple in-memory cache and refresh logic wouldn't take more than a few lines of code, but I just felt that the new package should have this built-in because the old one had it, and I generally trust MS's internal implementation on this sort of things more than my own. |
duplicate of #25361 |
Update network readme.python.md (Azure#20011) * Update network readme.python.md * Update readme.python.md Co-authored-by: Zhenbiao Wei (WICRESOFT NORTH AMERICA LTD) <[email protected]> Co-authored-by: Yuchao Yan <[email protected]>
I was reading this documentation and getting ready to migrate from
AppAuthentication
toAzure.Identity
.While the new library surely works amazingly well with the new Azure client SDKs, I soon found out that the method to directly obtain access token,
TokenCredential.GetTokenAsync
, has the following warning:There are plenty of use cases where a managed identity access token needs to be explicitly retrieved. For example, using Entity Framework Core with either Azure SQL or Azure PostgreSQL with managed identity requires that the actual tokens to be passed to the EF provider. Same with authenticating against a custom Azure AD enterprise application via standard
HttpClient
.These scenarios are unlikely to get native integration with
Azure.Identity
anytime soon.The older library's
AzureServiceTokenProvider.GetAccessTokenAsync
has built-in token caching and refreshing which works fairly well. It would be great ifAzure.Identity
can implement the same. Only then it will become a viable full replacement forAppAuthentication
.In the meantime, I believe this difference should be noted in the migration documentation under the "Access token retrieval" section.
The text was updated successfully, but these errors were encountered: