102 lines
3.0 KiB
C#
102 lines
3.0 KiB
C#
using System.Net.Http.Json;
|
|
using System.Security.Claims;
|
|
using ChessCubing.App.Models.Auth;
|
|
using Microsoft.AspNetCore.Components.Authorization;
|
|
|
|
namespace ChessCubing.App.Services;
|
|
|
|
public sealed class AppAuthenticationStateProvider(HttpClient httpClient) : AuthenticationStateProvider
|
|
{
|
|
private static readonly AuthenticationState AnonymousState = new(new ClaimsPrincipal(new ClaimsIdentity()));
|
|
|
|
private AuthenticationState? _cachedState;
|
|
|
|
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
|
|
{
|
|
if (_cachedState is not null)
|
|
{
|
|
return _cachedState;
|
|
}
|
|
|
|
_cachedState = await LoadStateAsync();
|
|
return _cachedState;
|
|
}
|
|
|
|
public async Task RefreshAsync()
|
|
{
|
|
_cachedState = await LoadStateAsync();
|
|
NotifyAuthenticationStateChanged(Task.FromResult(_cachedState));
|
|
}
|
|
|
|
public void SetAuthenticated(AuthSessionResponse session)
|
|
{
|
|
_cachedState = new AuthenticationState(BuildPrincipal(session));
|
|
NotifyAuthenticationStateChanged(Task.FromResult(_cachedState));
|
|
}
|
|
|
|
public void SetAnonymous()
|
|
{
|
|
_cachedState = AnonymousState;
|
|
NotifyAuthenticationStateChanged(Task.FromResult(_cachedState));
|
|
}
|
|
|
|
private async Task<AuthenticationState> LoadStateAsync()
|
|
{
|
|
try
|
|
{
|
|
var session = await httpClient.GetFromJsonAsync<AuthSessionResponse>("api/auth/session");
|
|
if (session is null || !session.IsAuthenticated)
|
|
{
|
|
return AnonymousState;
|
|
}
|
|
|
|
return new AuthenticationState(BuildPrincipal(session));
|
|
}
|
|
catch
|
|
{
|
|
return AnonymousState;
|
|
}
|
|
}
|
|
|
|
private static ClaimsPrincipal BuildPrincipal(AuthSessionResponse session)
|
|
{
|
|
if (!session.IsAuthenticated)
|
|
{
|
|
return AnonymousState.User;
|
|
}
|
|
|
|
var claims = new List<Claim>();
|
|
|
|
if (!string.IsNullOrWhiteSpace(session.Subject))
|
|
{
|
|
claims.Add(new Claim("sub", session.Subject));
|
|
claims.Add(new Claim(ClaimTypes.NameIdentifier, session.Subject));
|
|
}
|
|
|
|
if (!string.IsNullOrWhiteSpace(session.Username))
|
|
{
|
|
claims.Add(new Claim("preferred_username", session.Username));
|
|
claims.Add(new Claim(ClaimTypes.Name, session.Username));
|
|
}
|
|
|
|
if (!string.IsNullOrWhiteSpace(session.Name))
|
|
{
|
|
claims.Add(new Claim("name", session.Name));
|
|
}
|
|
|
|
if (!string.IsNullOrWhiteSpace(session.Email))
|
|
{
|
|
claims.Add(new Claim("email", session.Email));
|
|
claims.Add(new Claim(ClaimTypes.Email, session.Email));
|
|
}
|
|
|
|
foreach (var role in session.Roles.Where(role => !string.IsNullOrWhiteSpace(role)))
|
|
{
|
|
claims.Add(new Claim("role", role));
|
|
claims.Add(new Claim(ClaimTypes.Role, role));
|
|
}
|
|
|
|
return new ClaimsPrincipal(new ClaimsIdentity(claims, "ChessCubingCookie"));
|
|
}
|
|
}
|