using System; using System.Linq; using System.Net.Http; using System.Net.Http.Headers; using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Flawless.Client.Remote; namespace Flawless.Client; public class AuthHeaderHandler : DelegatingHandler { private string? AuthenticationHeader { get; set; } protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { var response = await SendCommandAsync(request, cancellationToken); var retryCount = 0; while (response.Headers.TryGetValues("Token-Expired", out var expired) && expired.Any(s => s == "true")) { if (retryCount++ > 3) { AuthenticationHeader = null; throw new TimeoutException("Too many retries, login info was cleared"); } var refreshRequest = new HttpRequestMessage(HttpMethod.Post, "api/auth/refresh"); var refresh = await base.SendAsync(refreshRequest, cancellationToken); if (!response.IsSuccessStatusCode) throw new ApplicationException("Login is expired and require login!"); await using var st = await refresh.Content.ReadAsStreamAsync(cancellationToken); var tk = await JsonSerializer.DeserializeAsync(st, cancellationToken: cancellationToken) ?? throw new ApplicationException("Not able to refresh token, please login again!"); AuthenticationHeader = tk.Token; response = await SendCommandAsync(request, cancellationToken); } return response; } private Task SendCommandAsync(HttpRequestMessage request, CancellationToken cancellationToken) { // Prefill this header if (AuthenticationHeader != null) request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", AuthenticationHeader); return base.SendAsync(request, cancellationToken); } }