![]() |
VOOZH | about |
dotnet add package I-Synergy.Framework.AspNetCore.Authentication --version 2026.10618.11733
NuGet\Install-Package I-Synergy.Framework.AspNetCore.Authentication -Version 2026.10618.11733
<PackageReference Include="I-Synergy.Framework.AspNetCore.Authentication" Version="2026.10618.11733" />
<PackageVersion Include="I-Synergy.Framework.AspNetCore.Authentication" Version="2026.10618.11733" />Directory.Packages.props
<PackageReference Include="I-Synergy.Framework.AspNetCore.Authentication" />Project file
paket add I-Synergy.Framework.AspNetCore.Authentication --version 2026.10618.11733
#r "nuget: I-Synergy.Framework.AspNetCore.Authentication, 2026.10618.11733"
#:package I-Synergy.Framework.AspNetCore.Authentication@2026.10618.11733
#addin nuget:?package=I-Synergy.Framework.AspNetCore.Authentication&version=2026.10618.11733Install as a Cake Addin
#tool nuget:?package=I-Synergy.Framework.AspNetCore.Authentication&version=2026.10618.11733Install as a Cake Tool
Authentication and identity management extensions for ASP.NET Core applications. This package provides JWT token handling, claims-based authorization utilities, custom password validation, and integration with OpenIddict for OAuth 2.0/OpenID Connect workflows.
Install the package via NuGet:
dotnet add package I-Synergy.Framework.AspNetCore.Authentication
In your Program.cs:
using ISynergy.Framework.AspNetCore.Authentication.Options;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;
var builder = WebApplication.CreateBuilder(args);
// Configure JWT options
builder.Services.Configure<JwtOptions>(
builder.Configuration.GetSection(nameof(JwtOptions)));
var jwtOptions = builder.Configuration
.GetSection(nameof(JwtOptions))
.Get<JwtOptions>();
// Add JWT authentication
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = jwtOptions.Issuer,
ValidAudience = jwtOptions.Audience,
IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(jwtOptions.SymmetricKeySecret))
};
});
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.Run();
{
"JwtOptions": {
"SymmetricKeySecret": "your-secret-key-minimum-32-characters-long",
"Issuer": "https://your-api.com",
"Audience": "https://your-app.com"
}
}
Retrieve user information from ClaimsPrincipal:
using ISynergy.Framework.Core.Extensions;
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/[controller]")]
[Authorize]
public class UserController : ControllerBase
{
[HttpGet("profile")]
public IActionResult GetProfile()
{
// Get user ID from claims
var userId = User.GetUserId();
// Get username
var username = User.GetUserName();
// Get account ID (tenant identifier)
var accountId = User.GetAccountId();
// Get client ID
var clientId = User.GetClientId();
return Ok(new
{
UserId = userId,
Username = username,
AccountId = accountId,
ClientId = clientId
});
}
[HttpGet("claims")]
public IActionResult GetClaims()
{
// Get single claim value
var email = User.GetSingleClaim("email");
// Get multiple claims
var roles = User.GetClaims("role");
// Get claim as specific type
var age = User.GetSingleClaimAsInt("age");
// Get claim as enum
var status = User.GetSingleClaimAsEnum<UserStatus>("status");
// Check if claim exists
bool hasEmail = User.HasClaim("email");
return Ok(new
{
Email = email,
Roles = roles,
Age = age,
Status = status,
HasEmail = hasEmail
});
}
}
Configure enhanced password validation with regex patterns:
using ISynergy.Framework.AspNetCore.Authentication.Options;
using ISynergy.Framework.AspNetCore.Authentication.Validators;
using Microsoft.AspNetCore.Identity;
using System.Text.RegularExpressions;
var builder = WebApplication.CreateBuilder(args);
// Configure password options
builder.Services.Configure<IdentityPasswordOptions>(options =>
{
options.RequiredLength = 8;
options.RequireDigit = true;
options.RequireLowercase = true;
options.RequireUppercase = true;
options.RequireNonAlphanumeric = true;
options.RequiredUniqueChars = 4;
// Custom regex pattern for additional validation
// Example: Require at least one special character from a specific set
options.RequiredRegexMatch = new Regex(@"^(?=.*[!@#$%^&*])");
});
// Add Identity with custom password validator
builder.Services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddPasswordValidator<IdentityPasswordValidator<ApplicationUser>>();
Using claims with OpenIddict authentication:
using ISynergy.Framework.Core.Extensions;
using Microsoft.AspNetCore.Mvc;
using static OpenIddict.Abstractions.OpenIddictConstants;
[ApiController]
[Route("api/[controller]")]
[Authorize(AuthenticationSchemes = "OpenIddict.Validation.AspNetCore")]
public class SecureController : ControllerBase
{
[HttpGet("info")]
public IActionResult GetUserInfo()
{
// Claims are automatically extracted from OpenIddict tokens
var userId = User.GetUserId(); // Gets Claims.Subject
var username = User.GetUserName(); // Gets Claims.Username
var accountId = User.GetAccountId(); // Gets Claims.KeyId
var clientId = User.GetClientId(); // Gets Claims.ClientId
return Ok(new
{
UserId = userId,
Username = username,
AccountId = accountId,
ClientId = clientId
});
}
}
ISynergy.Framework.AspNetCore.Authentication.Options/
├── JwtOptions # JWT configuration (issuer, audience, secret)
└── IdentityPasswordOptions # Enhanced password validation with regex
ISynergy.Framework.Core.Extensions/
└── ClaimsPrincipalExtensions # Claims retrieval and conversion utilities
ISynergy.Framework.AspNetCore.Authentication.Validators/
└── IdentityPasswordValidator<T> # Custom password validator with regex support
ISynergy.Framework.AspNetCore.Authentication.Exceptions/
└── ClaimNotFoundExceptionFilterAttribute # Handle missing claims gracefully
using ISynergy.Framework.Core.Extensions;
public class ClaimsExample
{
public void ProcessUserClaims(ClaimsPrincipal user)
{
// Get single claim as string
var email = user.GetSingleClaim("email");
// Get single claim as int
var userId = user.GetSingleClaimAsInt("user_id");
// Get single claim as Guid
var tenantId = user.GetSingleClaimAsGuid("tenant_id");
// Get single claim as enum
var role = user.GetSingleClaimAsEnum<UserRole>("role");
// Get multiple claims as list
var permissions = user.GetClaims("permission");
// Get multiple claims as int list
var groupIds = user.GetClaimsAsInt("group_id");
// Get multiple claims as enum list
var scopes = user.GetClaimsAsEnum<AccessScope>("scope");
}
}
public enum UserRole
{
User,
Admin,
SuperAdmin
}
public enum AccessScope
{
Read,
Write,
Delete
}
using ISynergy.Framework.Core.Exceptions;
using ISynergy.Framework.Core.Extensions;
public class SecureService
{
public string GetUserEmail(ClaimsPrincipal user)
{
try
{
// Throws ClaimNotFoundException if claim doesn't exist
return user.GetSingleClaim("email");
}
catch (ClaimNotFoundException ex)
{
// Handle missing claim
throw new UnauthorizedAccessException($"Missing required claim: {ex.Message}");
}
catch (DuplicateClaimException ex)
{
// Handle duplicate claims
throw new InvalidOperationException($"Duplicate claim found: {ex.Message}");
}
catch (InvalidClaimValueException ex)
{
// Handle invalid claim value (type conversion failed)
throw new ArgumentException($"Invalid claim value: {ex.Message}");
}
}
public bool TryGetUserEmail(ClaimsPrincipal user, out string email)
{
email = string.Empty;
// Safe check without throwing
if (!user.HasClaim("email"))
return false;
try
{
email = user.GetSingleClaim("email");
return true;
}
catch
{
return false;
}
}
}
using ISynergy.Framework.AspNetCore.Authentication.Options;
using System.Text.RegularExpressions;
// Example 1: Require at least one special character
var options1 = new IdentityPasswordOptions
{
RequiredLength = 8,
RequireDigit = true,
RequiredRegexMatch = new Regex(@"^(?=.*[!@#$%^&*(),.?""{}|<>])")
};
// Example 2: Prevent common password patterns
var options2 = new IdentityPasswordOptions
{
RequiredLength = 10,
RequiredRegexMatch = new Regex(@"^(?!.*(?:password|123456|qwerty))",
RegexOptions.IgnoreCase)
};
// Example 3: Require specific character sets
var options3 = new IdentityPasswordOptions
{
RequiredLength = 12,
RequiredRegexMatch = new Regex(
@"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&#])[A-Za-z\d@$!%*?&#]")
};
// Example 4: Maximum length restriction
var options4 = new IdentityPasswordOptions
{
RequiredLength = 8,
RequiredRegexMatch = new Regex(@"^.{8,50}$")
};
Complete example of a secure Web API:
using ISynergy.Framework.AspNetCore.Authentication.Options;
using ISynergy.Framework.Core.Extensions;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
var builder = WebApplication.CreateBuilder(args);
// Configure JWT
var jwtOptions = builder.Configuration
.GetSection(nameof(JwtOptions))
.Get<JwtOptions>();
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = jwtOptions.Issuer,
ValidAudience = jwtOptions.Audience,
IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(jwtOptions.SymmetricKeySecret)),
ClockSkew = TimeSpan.Zero
};
});
builder.Services.AddAuthorization();
builder.Services.AddControllers();
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
[ApiController]
[Route("api/[controller]")]
public class AuthController : ControllerBase
{
private readonly JwtOptions _jwtOptions;
public AuthController(IOptions<JwtOptions> jwtOptions)
{
_jwtOptions = jwtOptions.Value;
}
[HttpPost("login")]
public IActionResult Login([FromBody] LoginRequest request)
{
// Validate credentials (implement your own logic)
if (!ValidateCredentials(request.Username, request.Password))
return Unauthorized();
// Create claims
var claims = new[]
{
new Claim(Claims.Subject, request.UserId),
new Claim(Claims.Username, request.Username),
new Claim(Claims.KeyId, request.AccountId.ToString()),
new Claim(Claims.ClientId, "web-app"),
new Claim("email", request.Email),
new Claim("role", "User")
};
// Generate token
var key = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(_jwtOptions.SymmetricKeySecret));
var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
issuer: _jwtOptions.Issuer,
audience: _jwtOptions.Audience,
claims: claims,
expires: DateTime.UtcNow.AddHours(1),
signingCredentials: credentials);
var tokenString = new JwtSecurityTokenHandler().WriteToken(token);
return Ok(new { Token = tokenString });
}
[HttpGet("profile")]
[Authorize]
public IActionResult GetProfile()
{
return Ok(new
{
UserId = User.GetUserId(),
Username = User.GetUserName(),
AccountId = User.GetAccountId(),
Email = User.GetSingleClaim("email"),
Roles = User.GetClaims("role")
});
}
}
public record LoginRequest(
string UserId,
string Username,
string Password,
string Email,
Guid AccountId);
using ISynergy.Framework.Core.Extensions;
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/tenants/{tenantId}/[controller]")]
[Authorize]
public class TenantDataController : ControllerBase
{
[HttpGet]
public IActionResult GetData([FromRoute] Guid tenantId)
{
// Verify user belongs to this tenant
var userTenantId = User.GetAccountId();
if (userTenantId != tenantId)
return Forbid();
// Retrieve tenant-specific data
var data = GetTenantData(tenantId);
return Ok(data);
}
[HttpPost]
public IActionResult CreateData([FromRoute] Guid tenantId, [FromBody] DataModel data)
{
var userTenantId = User.GetAccountId();
if (userTenantId != tenantId)
return Forbid();
// Create tenant-specific data
data.TenantId = tenantId;
data.CreatedBy = User.GetUserId();
SaveData(data);
return CreatedAtAction(nameof(GetData), new { tenantId }, data);
}
}
Store JWT secrets securely using Azure Key Vault or environment variables instead of hardcoding them in configuration files.
Use HTTPS in production to protect JWT tokens from interception during transmission.
Set appropriate token expiration times based on your security requirements. Shorter lifetimes are more secure but may impact user experience.
Example unit tests for authentication components:
using ISynergy.Framework.Core.Extensions;
using System.Security.Claims;
using Xunit;
public class ClaimsExtensionsTests
{
[Fact]
public void GetUserId_WithValidClaim_ReturnsUserId()
{
// Arrange
var claims = new[]
{
new Claim(Claims.Subject, "user-123")
};
var identity = new ClaimsIdentity(claims);
var principal = new ClaimsPrincipal(identity);
// Act
var userId = principal.GetUserId();
// Assert
Assert.Equal("user-123", userId);
}
[Fact]
public void GetAccountId_WithValidClaim_ReturnsGuid()
{
// Arrange
var accountId = Guid.NewGuid();
var claims = new[]
{
new Claim(Claims.KeyId, accountId.ToString())
};
var identity = new ClaimsIdentity(claims);
var principal = new ClaimsPrincipal(identity);
// Act
var result = principal.GetAccountId();
// Assert
Assert.Equal(accountId, result);
}
[Fact]
public void HasClaim_WithExistingClaim_ReturnsTrue()
{
// Arrange
var claims = new[]
{
new Claim("email", "test@example.com")
};
var identity = new ClaimsIdentity(claims);
var principal = new ClaimsPrincipal(identity);
// Act
var result = principal.HasClaim("email");
// Assert
Assert.True(result);
}
}
For more information about the I-Synergy Framework:
For issues, questions, or contributions, please visit the GitHub repository.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 net10.0 is compatible. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
Showing the top 3 NuGet packages that depend on I-Synergy.Framework.AspNetCore.Authentication:
| Package | Downloads |
|---|---|
|
I-Synergy.Framework.AspNetCore.MultiTenancy
I-Synergy Framework MultiTenancy |
|
|
I-Synergy.Framework.Monitoring.SignalR
I-Synergy Framework SignalR Monitoring for .net 8.0 |
|
|
I-Synergy.Framework.AspNetCore.Monitoring
I-Synergy Framework AspNetCore SignalR Monitoring |
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2026.10618.11733 | 0 | 6/18/2026 |
| 2026.10618.11702-preview | 0 | 6/18/2026 |
| 2026.10616.12121 | 72 | 6/16/2026 |
| 2026.10616.11904-preview | 52 | 6/16/2026 |
| 2026.10616.10010 | 63 | 6/15/2026 |
| 2026.10615.12240-preview | 65 | 6/15/2026 |
| 2026.10615.10047-preview | 64 | 6/14/2026 |
| 2026.10614.10112-preview | 71 | 6/13/2026 |
| 2026.10612.12341-preview | 78 | 6/12/2026 |
| 2026.10612.12110-preview | 64 | 6/12/2026 |
| 2026.10612.11941-preview | 73 | 6/12/2026 |
| 2026.10610.10831 | 109 | 6/10/2026 |
| 2026.10610.10706-preview-pr... | 101 | 6/10/2026 |
| 2026.10609.11323-preview | 99 | 6/9/2026 |
| 2026.10607.11905-preview | 106 | 6/7/2026 |
| 2026.10607.11454-preview | 111 | 6/7/2026 |
| 2026.10606.11854-preview | 113 | 6/6/2026 |
| 2026.10603.11238-preview | 108 | 6/3/2026 |
| 2026.10602.12203-preview | 107 | 6/2/2026 |
| 2026.10602.11949-preview | 119 | 6/2/2026 |