9cad9ed0fc
v2-ci / build (push) Failing after 41s
v2-ci / unit-tests (tests/Core/ZB.MOM.WW.OtOpcUa.Cluster.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Security.Tests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests) (push) Has been skipped
Adds <summary>/<param>/<returns>/<inheritdoc> where missing and removes project bookkeeping IDs (task/tracking refs) from shipped code comments, so the docs read cleanly and CommentChecker is quiet except for known false positives (PLC/protocol terms, event/IEqualityComparer inheritdoc). Doc/comment-only; no logic changed; solution builds clean.
80 lines
3.1 KiB
C#
80 lines
3.1 KiB
C#
using System.Net.Http.Json;
|
|
using System.Security.Claims;
|
|
using Microsoft.AspNetCore.Components.Authorization;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace ZB.MOM.WW.OtOpcUa.Security.Blazor;
|
|
|
|
/// <summary>
|
|
/// Blazor Server <see cref="AuthenticationStateProvider"/> that snapshots the cookie-backed
|
|
/// principal supplied at circuit boot and polls <c>/auth/ping</c> every 60 seconds to detect
|
|
/// expiry. Mirrors ScadaLink's CentralUI implementation.
|
|
/// </summary>
|
|
public sealed class CookieAuthenticationStateProvider : AuthenticationStateProvider, IAsyncDisposable
|
|
{
|
|
private static readonly TimeSpan PingInterval = TimeSpan.FromSeconds(60);
|
|
|
|
private readonly HttpClient _http;
|
|
private readonly ILogger<CookieAuthenticationStateProvider> _logger;
|
|
private readonly CancellationTokenSource _cts = new();
|
|
private ClaimsPrincipal _current;
|
|
private Task? _pingLoop;
|
|
|
|
/// <summary>Initializes a new instance of the CookieAuthenticationStateProvider class.</summary>
|
|
/// <param name="initial">The initial claims principal from circuit boot.</param>
|
|
/// <param name="http">The HTTP client for authentication ping requests.</param>
|
|
/// <param name="logger">The logger for diagnostic messages.</param>
|
|
public CookieAuthenticationStateProvider(
|
|
ClaimsPrincipal initial,
|
|
HttpClient http,
|
|
ILogger<CookieAuthenticationStateProvider> logger)
|
|
{
|
|
_current = initial;
|
|
_http = http;
|
|
_logger = logger;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public override Task<AuthenticationState> GetAuthenticationStateAsync()
|
|
{
|
|
_pingLoop ??= Task.Run(() => PingLoopAsync(_cts.Token));
|
|
return Task.FromResult(new AuthenticationState(_current));
|
|
}
|
|
|
|
private async Task PingLoopAsync(CancellationToken ct)
|
|
{
|
|
try
|
|
{
|
|
while (!ct.IsCancellationRequested)
|
|
{
|
|
await Task.Delay(PingInterval, ct).ConfigureAwait(false);
|
|
var resp = await _http.GetAsync("/auth/ping", ct).ConfigureAwait(false);
|
|
if (!resp.IsSuccessStatusCode && _current.Identity?.IsAuthenticated == true)
|
|
{
|
|
_logger.LogInformation("/auth/ping returned {Code}; notifying circuit", (int)resp.StatusCode);
|
|
_current = new ClaimsPrincipal(new ClaimsIdentity());
|
|
NotifyAuthenticationStateChanged(
|
|
Task.FromResult(new AuthenticationState(_current)));
|
|
}
|
|
}
|
|
}
|
|
catch (OperationCanceledException) { /* expected on shutdown */ }
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogWarning(ex, "Auth ping loop terminated unexpectedly");
|
|
}
|
|
}
|
|
|
|
/// <summary>Cancels the background ping loop, awaits its completion, and disposes the cancellation token source.</summary>
|
|
/// <returns>A task that represents the asynchronous operation.</returns>
|
|
public async ValueTask DisposeAsync()
|
|
{
|
|
_cts.Cancel();
|
|
if (_pingLoop is not null)
|
|
{
|
|
try { await _pingLoop.ConfigureAwait(false); } catch { /* swallow shutdown errors */ }
|
|
}
|
|
_cts.Dispose();
|
|
}
|
|
}
|