LANCommander/LANCommander.Server/Startup/RolesClaimAction.cs
Pat Hartl f1fa66b632 Improve advanced auth provider editing, add role claim mapping
- Added auto discovery of scopes and claim mappings to auth provider editor
- Added the ability to map claims to roles
- Auto-provision users logged in over external auth

Ref #411
2026-06-21 02:03:51 -05:00

69 lines
1.9 KiB
C#

using System.Security.Claims;
using System.Text.Json;
using Microsoft.AspNetCore.Authentication.OAuth.Claims;
namespace LANCommander.Server.Startup;
/// <summary>
/// A claim action that projects a provider's role/group claim onto one claim per value.
/// Unlike <c>MapJsonKey</c>, this expands JSON arrays into multiple claims and supports
/// dotted paths for nested claims (e.g. Keycloak's <c>realm_access.roles</c>).
/// </summary>
public class RolesClaimAction : ClaimAction
{
private readonly string _jsonKey;
public RolesClaimAction(string claimType, string jsonKey)
: base(claimType, ClaimValueTypes.String)
{
_jsonKey = jsonKey;
}
public override void Run(JsonElement userData, ClaimsIdentity identity, string issuer)
{
if (userData.ValueKind != JsonValueKind.Object)
return;
if (!TryResolve(userData, _jsonKey, out var element))
return;
if (element.ValueKind == JsonValueKind.Array)
{
foreach (var item in element.EnumerateArray())
AddClaim(item, identity, issuer);
}
else
{
AddClaim(element, identity, issuer);
}
}
private void AddClaim(JsonElement element, ClaimsIdentity identity, string issuer)
{
if (element.ValueKind != JsonValueKind.String)
return;
var value = element.GetString();
if (!string.IsNullOrWhiteSpace(value))
identity.AddClaim(new Claim(ClaimType, value, ValueType, issuer));
}
private static bool TryResolve(JsonElement root, string path, out JsonElement value)
{
value = root;
foreach (var segment in path.Split('.'))
{
if (value.ValueKind != JsonValueKind.Object || !value.TryGetProperty(segment, out var next))
{
value = default;
return false;
}
value = next;
}
return true;
}
}