Integrer l'authentification Keycloak dans l'application

This commit is contained in:
2026-04-13 23:59:20 +02:00
parent 53f0af761e
commit 9b739b02f6
20 changed files with 1201 additions and 276 deletions

View File

@@ -0,0 +1,101 @@
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"));
}
}