Compare commits

...

2 Commits

Author SHA1 Message Date
Maksym Sadovnychyy
ab763d7c8f (feature): deps update 2025-10-16 20:54:15 +02:00
Maksym Sadovnychyy
d121f045bd (feature): custom jwt acl entry claim support 2025-10-16 20:37:31 +02:00
5 changed files with 36 additions and 11 deletions

View File

@ -8,31 +8,32 @@
<!-- NuGet package metadata --> <!-- NuGet package metadata -->
<PackageId>MaksIT.Core</PackageId> <PackageId>MaksIT.Core</PackageId>
<Version>1.4.5</Version> <Version>1.4.7</Version>
<Authors>Maksym Sadovnychyy</Authors> <Authors>Maksym Sadovnychyy</Authors>
<Company>MAKS-IT</Company> <Company>MAKS-IT</Company>
<Product>MaksIT.Core</Product> <Product>MaksIT.Core</Product>
<Description>MaksIT.Core is a collection of helper methods and extensions for .NET projects, designed to simplify common tasks and improve code readability. The library includes extensions for `Guid`, `string`, `Object`, and a base class for creating enumeration types.</Description> <Description>MaksIT.Core is a collection of helper methods and extensions for .NET projects, designed to simplify common tasks and improve code readability. The library includes extensions for `Guid`, `string`, `Object`, and a base class for creating enumeration types.</Description>
<PackageTags>dotnet;enumeration;string;guid;object;parsers;extensions;jwt;aes;crc32;</PackageTags> <PackageTags>dotnet;enumeration;string;guid;object;parsers;extensions;jwt;aes;crc32;</PackageTags>
<RepositoryUrl>https://github.com/MAKS-IT-COM/maksit-core</RepositoryUrl> <RepositoryUrl>https://github.com/MAKS-IT-COM/maksit-core</RepositoryUrl>
<License>MIT</License>
<RequireLicenseAcceptance>false</RequireLicenseAcceptance> <RequireLicenseAcceptance>false</RequireLicenseAcceptance>
<PackageReadmeFile>README.md</PackageReadmeFile> <PackageReadmeFile>README.md</PackageReadmeFile>
<PackageLicenseFile>LICENSE.md</PackageLicenseFile>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<None Include="../../README.md" Pack="true" PackagePath="" /> <None Include="../../README.md" Pack="true" PackagePath="" />
<None Include="../../LICENSE.md" Pack="true" PackagePath="" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="9.0.5" /> <PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="9.0.10" />
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.3.0" /> <PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.3.0" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.5" /> <PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.10" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.5" /> <PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.10" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.5" /> <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.10" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="9.0.5" /> <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="9.0.10" />
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="8.11.0" /> <PackageReference Include="Microsoft.IdentityModel.Tokens" Version="8.14.0" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.11.0" /> <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.14.0" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.6.4" /> <PackageReference Include="System.Linq.Dynamic.Core" Version="1.6.9" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -0,0 +1,12 @@
using MaksIT.Core.Abstractions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MaksIT.Core.Security.JWT;
public class CustomClaims : Enumeration {
public static readonly CustomClaims AclEntry = new(1, "acl_entry");
private CustomClaims(int id, string name) : base(id, name) { }
}

View File

@ -17,6 +17,8 @@ public class JWTTokenClaims {
/// </summary> /// </summary>
public List<string>? Roles { get; set; } public List<string>? Roles { get; set; }
public List<string>? AclEntries { get; set; }
/// <summary> /// <summary>
/// Gets or sets the date and time when the token was issued. /// Gets or sets the date and time when the token was issued.
/// </summary> /// </summary>

View File

@ -37,4 +37,7 @@ public class JWTTokenGenerateRequest {
/// </summary> /// </summary>
public List<string>? Roles { get; set; } public List<string>? Roles { get; set; }
public List<string>? AclEntries { get; set; }
} }

View File

@ -8,8 +8,10 @@ using System.Text;
namespace MaksIT.Core.Security.JWT; namespace MaksIT.Core.Security.JWT;
public static class JwtGenerator {
public static class JwtGenerator {
/// <summary> /// <summary>
/// Attempts to generate a JWT token using the specified request parameters. /// Attempts to generate a JWT token using the specified request parameters.
/// </summary> /// </summary>
@ -49,6 +51,9 @@ public static class JwtGenerator {
if (request.Roles !=null) if (request.Roles !=null)
claims.AddRange(request.Roles.Select(role => new Claim(ClaimTypes.Role, role))); claims.AddRange(request.Roles.Select(role => new Claim(ClaimTypes.Role, role)));
if (request.AclEntries != null)
claims.AddRange(request.AclEntries.Select(acl => new Claim(CustomClaims.AclEntry.Name, acl)));
var tokenDescriptor = new JwtSecurityToken( var tokenDescriptor = new JwtSecurityToken(
issuer: request.Issuer, issuer: request.Issuer,
audience: request.Audience, audience: request.Audience,
@ -141,6 +146,7 @@ public static class JwtGenerator {
var username = principal.Identity?.Name; var username = principal.Identity?.Name;
var roles = principal.Claims.Where(c => c.Type == ClaimTypes.Role).Select(c => c.Value).ToList(); var roles = principal.Claims.Where(c => c.Type == ClaimTypes.Role).Select(c => c.Value).ToList();
var aclEntries = principal.Claims.Where(c => c.Type == CustomClaims.AclEntry.Name).Select(c => c.Value).ToList();
var issuedAtClaim = principal.Claims.FirstOrDefault(c => c.Type == JwtRegisteredClaimNames.Iat)?.Value; var issuedAtClaim = principal.Claims.FirstOrDefault(c => c.Type == JwtRegisteredClaimNames.Iat)?.Value;
var expiresAtClaim = principal.Claims.FirstOrDefault(c => c.Type == JwtRegisteredClaimNames.Exp)?.Value; var expiresAtClaim = principal.Claims.FirstOrDefault(c => c.Type == JwtRegisteredClaimNames.Exp)?.Value;
@ -152,6 +158,7 @@ public static class JwtGenerator {
UserId = userId, UserId = userId,
Username = username, Username = username,
Roles = roles, Roles = roles,
AclEntries = aclEntries,
IssuedAt = issuedAt, IssuedAt = issuedAt,
ExpiresAt = expiresAt ExpiresAt = expiresAt
}; };