2024-07-11 09:11:01 -07:00

108 lines
4.9 KiB
C#

using System.Net;
using System.Text.Json;
using System.Text;
using MesaFabApproval.Shared.Models;
using Microsoft.Extensions.Caching.Memory;
using System.Net.Http.Headers;
using MesaFabApproval.Client.Services;
using Microsoft.AspNetCore.Components;
namespace MesaFabApproval.Client.Utilities;
public class ApiHttpClientHandler : DelegatingHandler {
private readonly IMemoryCache _cache;
private readonly IAuthenticationService _authService;
private readonly MesaFabApprovalAuthStateProvider _authStateProvider;
private readonly NavigationManager _navigationManager;
private readonly string _apiBaseUrl;
public ApiHttpClientHandler(IMemoryCache cache,
IConfiguration config,
IAuthenticationService authService,
MesaFabApprovalAuthStateProvider authStateProvider,
NavigationManager navigationManager) {
_cache = cache ?? throw new ArgumentNullException("IMemoryCache not injected");
_apiBaseUrl = config["FabApprovalApiBaseUrl"] ??
throw new NullReferenceException("FabApprovalApiBaseUrl not found in config");
_authService = authService ??
throw new ArgumentNullException("IAuthenticationService not injected");
_authStateProvider = authStateProvider ??
throw new ArgumentNullException("MesaFabApprovalAuthStateProvider not injected");
_navigationManager = navigationManager ??
throw new ArgumentNullException("NavigationManager not injected");
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage requestMessage,
CancellationToken cancellationToken) {
AuthTokens? authTokens = await _authService.GetAuthTokens();
if (authTokens is not null) requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authTokens.JwtToken);
HttpResponseMessage responseMessage = await base.SendAsync(requestMessage, cancellationToken);
if (responseMessage.StatusCode.Equals(HttpStatusCode.Unauthorized)) {
string? loginId = await _authService.GetLoginId();
if (!string.IsNullOrWhiteSpace(loginId) && authTokens is not null) {
AuthAttempt authAttempt = new() {
LoginID = loginId,
AuthTokens = authTokens
};
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "auth/refresh");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authTokens.JwtToken);
request.Content = new StringContent(JsonSerializer.Serialize(authAttempt),
Encoding.UTF8,
"application/json");
HttpClient httpClient = new HttpClient() {
BaseAddress = new Uri(_apiBaseUrl)
};
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("*/*"));
HttpResponseMessage httpResponseMessage = await httpClient.SendAsync(request, cancellationToken);
if (httpResponseMessage.IsSuccessStatusCode) {
string responseContent = await httpResponseMessage.Content.ReadAsStringAsync();
JsonSerializerOptions jsonSerializerOptions = new() {
PropertyNameCaseInsensitive = true
};
LoginResult loginResult = JsonSerializer.Deserialize<LoginResult>(responseContent, jsonSerializerOptions) ??
throw new Exception("Unable to parse login result from API response");
if (!loginResult.IsAuthenticated) throw new Exception($"User with Login ID {loginId} not authorized");
if (loginResult.AuthTokens is not null) {
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", loginResult.AuthTokens.JwtToken);
await _authService.SetTokens(loginResult.AuthTokens.JwtToken, loginResult.AuthTokens.RefreshToken);
}
if (loginResult.User is not null)
await _authService.SetCurrentUser(loginResult.User);
} else {
await _authStateProvider.Logout();
string? redirectUrl = _cache.Get<string>("redirectUrl");
if (!string.IsNullOrWhiteSpace(redirectUrl)) {
_navigationManager.NavigateTo($"login/{redirectUrl}");
} else {
_navigationManager.NavigateTo("login");
}
}
}
return await base.SendAsync(requestMessage, cancellationToken);
}
return responseMessage;
}
}