54 lines
1.9 KiB
C#
54 lines
1.9 KiB
C#
using System.Security.Claims;
|
|
using System.Text.Json;
|
|
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
|
|
using Microsoft.AspNetCore.Components.WebAssembly.Authentication.Internal;
|
|
|
|
namespace ChessCubing.App.Services;
|
|
|
|
public sealed class KeycloakAccountFactory(IAccessTokenProviderAccessor accessor)
|
|
: AccountClaimsPrincipalFactory<RemoteUserAccount>(accessor)
|
|
{
|
|
public override async ValueTask<ClaimsPrincipal> CreateUserAsync(
|
|
RemoteUserAccount account,
|
|
RemoteAuthenticationUserOptions options)
|
|
{
|
|
var user = await base.CreateUserAsync(account, options);
|
|
if (user.Identity is not ClaimsIdentity identity || !identity.IsAuthenticated)
|
|
{
|
|
return user;
|
|
}
|
|
|
|
var roleClaimType = options.RoleClaim ?? "role";
|
|
var existingRoles = identity.FindAll(roleClaimType)
|
|
.Select(claim => claim.Value)
|
|
.ToHashSet(StringComparer.OrdinalIgnoreCase);
|
|
|
|
foreach (var role in ReadRealmRoles(account))
|
|
{
|
|
if (existingRoles.Add(role))
|
|
{
|
|
identity.AddClaim(new Claim(roleClaimType, role));
|
|
}
|
|
}
|
|
|
|
return user;
|
|
}
|
|
|
|
private static IEnumerable<string> ReadRealmRoles(RemoteUserAccount account)
|
|
{
|
|
if (!account.AdditionalProperties.TryGetValue("realm_access", out var realmAccessValue) ||
|
|
realmAccessValue is not JsonElement realmAccessElement ||
|
|
realmAccessElement.ValueKind != JsonValueKind.Object ||
|
|
!realmAccessElement.TryGetProperty("roles", out var rolesElement) ||
|
|
rolesElement.ValueKind != JsonValueKind.Array)
|
|
{
|
|
return [];
|
|
}
|
|
|
|
return rolesElement.EnumerateArray()
|
|
.Where(item => item.ValueKind == JsonValueKind.String)
|
|
.Select(item => item.GetString())
|
|
.OfType<string>();
|
|
}
|
|
}
|