From ce69779c9f726525ee9aeb17b60fe41eed3f5bab Mon Sep 17 00:00:00 2001 From: TekH Date: Tue, 3 Feb 2026 13:58:32 +0100 Subject: [PATCH] Enhance JWT user claims with configurable roles Updated Program.cs to include "CommonUserRoles" from configuration in JWT claims for users, adding them under ClaimTypes.Role if present. Also added System.Security.Claims using directive to support this change. This enables dynamic role assignment in user tokens. --- src/DigitalData.Auth.API/Program.cs | 41 ++++++++++++++++++----------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/src/DigitalData.Auth.API/Program.cs b/src/DigitalData.Auth.API/Program.cs index a632e03..375ef4b 100644 --- a/src/DigitalData.Auth.API/Program.cs +++ b/src/DigitalData.Auth.API/Program.cs @@ -9,12 +9,12 @@ using DigitalData.Core.Security.Extensions; using DigitalData.UserManager.Application; using DigitalData.UserManager.Application.DTOs.User; using Microsoft.AspNetCore.Authentication.JwtBearer; -using Microsoft.Extensions.Options; using Microsoft.IdentityModel.JsonWebTokens; using Microsoft.IdentityModel.Tokens; using Microsoft.OpenApi.Models; using NLog; using NLog.Web; +using System.Security.Claims; var logger = LogManager.Setup().LoadConfigurationFromAppSettings().GetCurrentClassLogger(); logger.Info("Logging initialized."); @@ -38,26 +38,37 @@ try var config = builder.Configuration; var apiParams = config.Get() ?? throw new InvalidOperationException("AuthApiOptions is missing or invalid in appsettings."); - + // Add services to the container. builder.Services.Configure(config.GetSection(nameof(BackdoorParams))); builder.Services.Configure(config); builder.Services.AddAuthService(config); builder.Services.AddRSAPool(config.GetSection("CryptParams")); builder.Services.AddJwtSignatureHandler(api => new Dictionary -{ - { JwtRegisteredClaimNames.Sub, api.Id }, - { JwtRegisteredClaimNames.Iat, DateTimeOffset.UtcNow.ToUnixTimeSeconds() } -}); - builder.Services.AddJwtSignatureHandler(user => new Dictionary -{ - { JwtRegisteredClaimNames.Sub, user.Id }, - { JwtRegisteredClaimNames.UniqueName, user.Username }, - { JwtRegisteredClaimNames.Email, user.Email ?? string.Empty }, - { JwtRegisteredClaimNames.GivenName, user.Prename ?? string.Empty }, - { JwtRegisteredClaimNames.FamilyName, user.Name ?? string.Empty }, - { JwtRegisteredClaimNames.Iat, DateTimeOffset.UtcNow.ToUnixTimeSeconds() } -}); + { + { JwtRegisteredClaimNames.Sub, api.Id }, + { JwtRegisteredClaimNames.Iat, DateTimeOffset.UtcNow.ToUnixTimeSeconds() } + }); + + var commonUserRoles = config.GetSection("CommonUserRoles").Get()?.Where(r => !string.IsNullOrWhiteSpace(r)).ToArray() ?? Array.Empty(); + + builder.Services.AddJwtSignatureHandler(user => + { + var claims = new Dictionary + { + { JwtRegisteredClaimNames.Sub, user.Id }, + { JwtRegisteredClaimNames.UniqueName, user.Username }, + { JwtRegisteredClaimNames.Email, user.Email ?? string.Empty }, + { JwtRegisteredClaimNames.GivenName, user.Prename ?? string.Empty }, + { JwtRegisteredClaimNames.FamilyName, user.Name ?? string.Empty }, + { JwtRegisteredClaimNames.Iat, DateTimeOffset.UtcNow.ToUnixTimeSeconds() } + }; + + if (commonUserRoles.Length > 0) + claims.Add(ClaimTypes.Role, commonUserRoles); + + return claims; + }); builder.Services.AddDirectorySearchService(config.GetSection("DirectorySearchOptions")); builder.Services.AddSignalR();