(feature): adding jwt user id and jwt reqiest object

This commit is contained in:
Maksym Sadovnychyy 2024-12-07 17:45:54 +01:00
parent 1e51993d13
commit 2e2036c90d
2 changed files with 37 additions and 22 deletions

View File

@ -8,7 +8,7 @@
<!-- NuGet package metadata --> <!-- NuGet package metadata -->
<PackageId>MaksIT.Core</PackageId> <PackageId>MaksIT.Core</PackageId>
<Version>1.2.1</Version> <Version>1.2.2</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>

View File

@ -2,49 +2,58 @@
using System.Security.Claims; using System.Security.Claims;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.IdentityModel.Tokens.Jwt; using System.IdentityModel.Tokens.Jwt;
using Microsoft.IdentityModel.Tokens;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using Microsoft.IdentityModel.Tokens;
namespace MaksIT.Core.Security; namespace MaksIT.Core.Security;
public class JWTTokenClaims { public class JWTTokenClaims {
public required string? Username { get; set; } public string? UserId { get; set; }
public required List<string>? Roles { get; set; } public string? Username { get; set; }
public List<string>? Roles { get; set; }
public DateTime? IssuedAt { get; set; } public DateTime? IssuedAt { get; set; }
public DateTime? ExpiresAt { get; set; } public DateTime? ExpiresAt { get; set; }
} }
public class JWTTokenGenerateRequest {
public required string Secret { get; set; }
public required string Issuer { get; set; }
public required string Audience { get; set; }
public double Expiration { get; set; }
public string? UserId { get; set; }
public string? Username { get; set; }
public List<string>? Roles { get; set; }
}
public static class JwtGenerator { public static class JwtGenerator {
public static bool TryGenerateToken( public static bool TryGenerateToken(JWTTokenGenerateRequest request, [NotNullWhen(true)] out (string, JWTTokenClaims)? tokenData, [NotNullWhen(false)] out string? errorMessage) {
string secret,
string issuer,
string audience,
double expiration,
string username,
List<string> roles,
[NotNullWhen(true)] out (string, JWTTokenClaims)? tokenData,
[NotNullWhen(false)] out string? errorMessage
) {
try { try {
var secretKey = GetSymmetricSecurityKey(secret); var secretKey = GetSymmetricSecurityKey(request.Secret);
var credentials = new SigningCredentials(secretKey, SecurityAlgorithms.HmacSha256); var credentials = new SigningCredentials(secretKey, SecurityAlgorithms.HmacSha256);
var issuedAt = DateTime.UtcNow; var issuedAt = DateTime.UtcNow;
var expiresAt = issuedAt.AddMinutes(expiration); var expiresAt = issuedAt.AddMinutes(request.Expiration);
var claims = new List<Claim> var claims = new List<Claim>
{ {
new Claim(ClaimTypes.Name, username),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(JwtRegisteredClaimNames.Iat, new DateTimeOffset(issuedAt).ToUnixTimeSeconds().ToString(), ClaimValueTypes.Integer64), new Claim(JwtRegisteredClaimNames.Iat, new DateTimeOffset(issuedAt).ToUnixTimeSeconds().ToString(), ClaimValueTypes.Integer64),
new Claim(JwtRegisteredClaimNames.Exp, new DateTimeOffset(expiresAt).ToUnixTimeSeconds().ToString(), ClaimValueTypes.Integer64) new Claim(JwtRegisteredClaimNames.Exp, new DateTimeOffset(expiresAt).ToUnixTimeSeconds().ToString(), ClaimValueTypes.Integer64)
}; };
claims.AddRange(roles.Select(role => new Claim(ClaimTypes.Role, role))); if (request.UserId != null)
claims.Add(new Claim(ClaimTypes.NameIdentifier, request.UserId));
if (request.Username != null)
claims.Add(new Claim(ClaimTypes.Name, request.Username));
if (request.Roles !=null)
claims.AddRange(request.Roles.Select(role => new Claim(ClaimTypes.Role, role)));
var tokenDescriptor = new JwtSecurityToken( var tokenDescriptor = new JwtSecurityToken(
issuer: issuer, issuer: request.Issuer,
audience: audience, audience: request.Audience,
claims: claims, claims: claims,
expires: expiresAt, expires: expiresAt,
signingCredentials: credentials signingCredentials: credentials
@ -53,12 +62,15 @@ public static class JwtGenerator {
var jwtToken = new JwtSecurityTokenHandler().WriteToken(tokenDescriptor); var jwtToken = new JwtSecurityTokenHandler().WriteToken(tokenDescriptor);
var tokenClaims = new JWTTokenClaims { var tokenClaims = new JWTTokenClaims {
Username = username, UserId = request.UserId,
Roles = roles, Username = request.Username,
IssuedAt = issuedAt, IssuedAt = issuedAt,
ExpiresAt = expiresAt ExpiresAt = expiresAt
}; };
if (request.Roles != null)
tokenClaims.Roles = request.Roles;
tokenData = (jwtToken, tokenClaims); tokenData = (jwtToken, tokenClaims);
errorMessage = null; errorMessage = null;
return true; return true;
@ -116,6 +128,8 @@ public static class JwtGenerator {
// Private helper method to extract claims // Private helper method to extract claims
private static JWTTokenClaims? ExtractClaims(ClaimsPrincipal principal) { private static JWTTokenClaims? ExtractClaims(ClaimsPrincipal principal) {
var userId = principal.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value;
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();
@ -126,6 +140,7 @@ public static class JwtGenerator {
DateTime? expiresAt = expiresAtClaim != null ? DateTimeOffset.FromUnixTimeSeconds(long.Parse(expiresAtClaim)).UtcDateTime : (DateTime?)null; DateTime? expiresAt = expiresAtClaim != null ? DateTimeOffset.FromUnixTimeSeconds(long.Parse(expiresAtClaim)).UtcDateTime : (DateTime?)null;
return new JWTTokenClaims { return new JWTTokenClaims {
UserId = userId,
Username = username, Username = username,
Roles = roles, Roles = roles,
IssuedAt = issuedAt, IssuedAt = issuedAt,