save progress
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
@@ -22,6 +23,7 @@ internal sealed class StellaOpsBearerTokenHandler : DelegatingHandler
|
||||
private readonly SemaphoreSlim refreshLock = new(1, 1);
|
||||
|
||||
private StellaOpsTokenResult? cachedToken;
|
||||
private string? cachedTokenKey;
|
||||
|
||||
public StellaOpsBearerTokenHandler(
|
||||
string clientName,
|
||||
@@ -67,9 +69,11 @@ internal sealed class StellaOpsBearerTokenHandler : DelegatingHandler
|
||||
|
||||
var buffer = GetRefreshBuffer(options);
|
||||
var now = timeProvider.GetUtcNow();
|
||||
var clientOptions = authClientOptions.CurrentValue;
|
||||
var cacheKey = BuildCacheKey(options, clientOptions);
|
||||
var token = cachedToken;
|
||||
|
||||
if (token is not null && token.ExpiresAt - buffer > now)
|
||||
if (token is not null && cachedTokenKey == cacheKey && token.ExpiresAt - buffer > now)
|
||||
{
|
||||
return token.AccessToken;
|
||||
}
|
||||
@@ -79,11 +83,30 @@ internal sealed class StellaOpsBearerTokenHandler : DelegatingHandler
|
||||
{
|
||||
token = cachedToken;
|
||||
now = timeProvider.GetUtcNow();
|
||||
if (token is not null && token.ExpiresAt - buffer > now)
|
||||
if (token is not null && cachedTokenKey == cacheKey && token.ExpiresAt - buffer > now)
|
||||
{
|
||||
return token.AccessToken;
|
||||
}
|
||||
|
||||
var cachedEntry = await tokenClient.GetCachedTokenAsync(cacheKey, cancellationToken).ConfigureAwait(false);
|
||||
if (cachedEntry is not null && !cachedEntry.IsExpired(timeProvider, buffer))
|
||||
{
|
||||
cachedToken = new StellaOpsTokenResult(
|
||||
cachedEntry.AccessToken,
|
||||
cachedEntry.TokenType,
|
||||
cachedEntry.ExpiresAtUtc,
|
||||
cachedEntry.Scopes,
|
||||
cachedEntry.RefreshToken,
|
||||
cachedEntry.IdToken,
|
||||
null);
|
||||
cachedTokenKey = cacheKey;
|
||||
return cachedEntry.AccessToken;
|
||||
}
|
||||
else if (cachedEntry is not null)
|
||||
{
|
||||
await tokenClient.ClearCachedTokenAsync(cacheKey, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
StellaOpsTokenResult result = options.Mode switch
|
||||
{
|
||||
StellaOpsApiAuthMode.ClientCredentials => await tokenClient.RequestClientCredentialsTokenAsync(
|
||||
@@ -100,6 +123,8 @@ internal sealed class StellaOpsBearerTokenHandler : DelegatingHandler
|
||||
};
|
||||
|
||||
cachedToken = result;
|
||||
cachedTokenKey = cacheKey;
|
||||
await tokenClient.CacheTokenAsync(cacheKey, result.ToCacheEntry(), cancellationToken).ConfigureAwait(false);
|
||||
logger?.LogDebug("Issued access token for client {ClientName}; expires at {ExpiresAt}.", clientName, result.ExpiresAt);
|
||||
return result.AccessToken;
|
||||
}
|
||||
@@ -120,4 +145,33 @@ internal sealed class StellaOpsBearerTokenHandler : DelegatingHandler
|
||||
|
||||
return buffer > authOptions.ExpirationSkew ? buffer : authOptions.ExpirationSkew;
|
||||
}
|
||||
|
||||
private string BuildCacheKey(StellaOpsApiAuthenticationOptions apiOptions, StellaOpsAuthClientOptions clientOptions)
|
||||
{
|
||||
var resolvedScope = ResolveScope(apiOptions.Scope, clientOptions);
|
||||
var authority = clientOptions.AuthorityUri?.ToString() ?? clientOptions.Authority;
|
||||
|
||||
var builder = new StringBuilder();
|
||||
builder.Append("stellaops|");
|
||||
builder.Append(clientName).Append('|');
|
||||
builder.Append(authority).Append('|');
|
||||
builder.Append(clientOptions.ClientId ?? string.Empty).Append('|');
|
||||
builder.Append(apiOptions.Mode).Append('|');
|
||||
builder.Append(resolvedScope ?? string.Empty).Append('|');
|
||||
builder.Append(apiOptions.Username ?? string.Empty).Append('|');
|
||||
builder.Append(apiOptions.Tenant ?? string.Empty);
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
private static string? ResolveScope(string? scope, StellaOpsAuthClientOptions clientOptions)
|
||||
{
|
||||
var resolved = scope;
|
||||
if (string.IsNullOrWhiteSpace(resolved) && clientOptions.NormalizedScopes.Count > 0)
|
||||
{
|
||||
resolved = string.Join(' ', clientOptions.NormalizedScopes);
|
||||
}
|
||||
|
||||
return string.IsNullOrWhiteSpace(resolved) ? null : resolved.Trim();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user