3e7120c041
WBS-9.3 - NULL Policy CI Gate / NULL Policy Validation (push) Failing after 5s
Quant Engine CI/CD Pipeline / validate-core (push) Failing after 10s
Quant Engine CI/CD Pipeline / validate-ui-and-storage (push) Has been skipped
Deploy to Production / Build & Deploy to Production (push) Failing after 1m49s
134 lines
5.2 KiB
C#
134 lines
5.2 KiB
C#
using System.Security.Claims;
|
|
using Microsoft.AspNetCore.Components.Authorization;
|
|
using QuantEngine.Web.Client.Services;
|
|
|
|
namespace QuantEngine.Web.Client.Infrastructure
|
|
{
|
|
public class CustomAuthenticationStateProvider : AuthenticationStateProvider
|
|
{
|
|
private readonly LocalStorageService _localStorage;
|
|
private readonly HttpClient _http;
|
|
private readonly ClaimsPrincipal _anonymous = new ClaimsPrincipal(new ClaimsIdentity());
|
|
private const string TokenKey = "quant_admin_access_token";
|
|
private const string UsernameKey = "quant_admin_username";
|
|
private const string RoleKey = "quant_admin_role";
|
|
private const string RememberUsernameKey = "quant_admin_remember_username";
|
|
|
|
public CustomAuthenticationStateProvider(LocalStorageService localStorage, HttpClient http)
|
|
{
|
|
_localStorage = localStorage;
|
|
_http = http;
|
|
}
|
|
|
|
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
|
|
{
|
|
try
|
|
{
|
|
var token = await _localStorage.GetAsync<string>(TokenKey);
|
|
var username = await _localStorage.GetAsync<string>(UsernameKey);
|
|
var role = await _localStorage.GetAsync<string>(RoleKey) ?? "Admin";
|
|
|
|
if (!string.IsNullOrWhiteSpace(token) && !string.IsNullOrWhiteSpace(username))
|
|
{
|
|
var request = new HttpRequestMessage(HttpMethod.Get, "api/auth/me");
|
|
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
|
|
var response = await _http.SendAsync(request);
|
|
if (!response.IsSuccessStatusCode)
|
|
{
|
|
await MarkUserAsLoggedOutAsync();
|
|
return new AuthenticationState(_anonymous);
|
|
}
|
|
|
|
var identity = new ClaimsIdentity(new[]
|
|
{
|
|
new Claim(ClaimTypes.Name, username),
|
|
new Claim(ClaimTypes.Role, role)
|
|
}, "QuantAdminAuth");
|
|
|
|
var user = new ClaimsPrincipal(identity);
|
|
return new AuthenticationState(user);
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
// Return anonymous if localStorage isn't ready
|
|
}
|
|
|
|
return new AuthenticationState(_anonymous);
|
|
}
|
|
|
|
public async Task MarkUserAsAuthenticatedAsync(string username, string accessToken, string role)
|
|
{
|
|
await MarkUserAsAuthenticatedAsync(username, accessToken, role, rememberUsername: true);
|
|
}
|
|
|
|
public async Task MarkUserAsAuthenticatedAsync(string username, string accessToken, string role, bool rememberUsername)
|
|
{
|
|
await _localStorage.SetAsync(TokenKey, accessToken);
|
|
if (rememberUsername)
|
|
{
|
|
await _localStorage.SetAsync(UsernameKey, username);
|
|
await _localStorage.SetAsync(RememberUsernameKey, true);
|
|
}
|
|
else
|
|
{
|
|
await _localStorage.DeleteAsync(UsernameKey);
|
|
await _localStorage.SetAsync(RememberUsernameKey, false);
|
|
}
|
|
await _localStorage.SetAsync(RoleKey, role);
|
|
|
|
var identity = new ClaimsIdentity(new[]
|
|
{
|
|
new Claim(ClaimTypes.Name, username),
|
|
new Claim(ClaimTypes.Role, role)
|
|
}, "QuantAdminAuth");
|
|
|
|
var user = new ClaimsPrincipal(identity);
|
|
NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(user)));
|
|
}
|
|
|
|
public async Task MarkUserAsLoggedOutAsync()
|
|
{
|
|
await _localStorage.DeleteAsync(TokenKey);
|
|
await _localStorage.DeleteAsync(RoleKey);
|
|
var rememberUsername = await _localStorage.GetAsync<bool>(RememberUsernameKey);
|
|
if (!rememberUsername)
|
|
{
|
|
await _localStorage.DeleteAsync(UsernameKey);
|
|
}
|
|
NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(_anonymous)));
|
|
}
|
|
|
|
public async Task LogoutFromServerAsync()
|
|
{
|
|
var token = await _localStorage.GetAsync<string>(TokenKey);
|
|
if (!string.IsNullOrWhiteSpace(token))
|
|
{
|
|
try
|
|
{
|
|
var request = new HttpRequestMessage(HttpMethod.Post, "api/auth/logout");
|
|
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
|
|
await _http.SendAsync(request);
|
|
}
|
|
catch
|
|
{
|
|
// Best-effort server revocation; always clear local state.
|
|
}
|
|
}
|
|
|
|
await MarkUserAsLoggedOutAsync();
|
|
}
|
|
|
|
public async Task<string?> GetRememberedUsernameAsync()
|
|
{
|
|
var rememberUsername = await _localStorage.GetAsync<bool>(RememberUsernameKey);
|
|
if (!rememberUsername)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return await _localStorage.GetAsync<string>(UsernameKey);
|
|
}
|
|
}
|
|
}
|