NAuth 0.5.10
dotnet add package NAuth --version 0.5.10
NuGet\Install-Package NAuth -Version 0.5.10
<PackageReference Include="NAuth" Version="0.5.10" />
<PackageVersion Include="NAuth" Version="0.5.10" />
<PackageReference Include="NAuth" />
paket add NAuth --version 0.5.10
#r "nuget: NAuth, 0.5.10"
#:package NAuth@0.5.10
#addin nuget:?package=NAuth&version=0.5.10
#tool nuget:?package=NAuth&version=0.5.10
NAuth
Unified library for the NAuth authentication and authorization ecosystem. Contains Data Transfer Objects (DTOs), HTTP client implementations (ACL), authentication handlers, JWT token processing, and multi-tenant support for user management, roles, and authentication.
Part of the NAuth ecosystem — see NAuth.API for the main project and full documentation.
Installation
Install via NuGet Package Manager:
dotnet add package NAuth
Or via Package Manager Console:
Install-Package NAuth
Migration from NAuth.DTO / NAuth.ACL: This package replaces both
NAuth.DTOandNAuth.ACL. Simply swap the package references — all namespaces (NAuth.DTO.*,NAuth.ACL.*) remain the same, so no code changes are needed.
Features
Data Transfer Objects (DTOs)
- User DTOs: Complete user data models for authentication and management
- Role DTOs: Role and permission data structures
- Authentication Models: Login parameters, token results, and password management
- Settings: Configuration objects for NAuth services (including tenant settings)
- Converters: Custom JSON converters for proper serialization
- Pagination: Generic paged result container
Access Control Layer (ACL)
- HTTP Clients: Ready-to-use HTTP clients for NAuth API
- User Management: Complete user CRUD operations via
IUserClient - Role Management: Role and permission handling via
IRoleClient - Authentication Handler: JWT validation middleware for ASP.NET Core
- Session Management: Extract user info from JWT claims
Multi-Tenant Support
- Automatic Tenant Header Injection:
TenantDelegatingHandleraddsX-Tenant-Idto all HTTP requests - Pluggable Tenant Resolution:
ITenantProviderinterface for custom tenant identification strategies - Per-Tenant JWT Secrets:
ITenantSecretProviderallows different JWT secrets per tenant - Built-in Settings Provider:
SettingsTenantProviderreads tenant ID fromNAuthSetting.TenantId - Simplified DI Registration:
AddNAuth()andAddNAuthAuthentication()extension methods
Quick Start
1. Configure Services
Add NAuth to your ASP.NET Core application using the new extension methods:
using NAuth.ACL;
using NAuth.DTO.Settings;
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// Configure NAuth settings
services.Configure<NAuthSetting>(Configuration.GetSection("NAuthSetting"));
// Register all NAuth services (clients, tenant provider, delegating handler)
services.AddNAuth();
// Add NAuth authentication handler
services.AddNAuthAuthentication();
}
}
The AddNAuth() method registers:
ITenantProvider(defaults toSettingsTenantProvider)TenantDelegatingHandlerfor automaticX-Tenant-Idheader injectionIUserClient/IRoleClientHTTP clients with the tenant handler in the pipeline
2. Configure appsettings.json
{
"NAuthSetting": {
"ApiUrl": "https://your-nauth-api.com/api",
"JwtSecret": "your-super-secret-jwt-key-min-64-characters",
"BucketName": "nauth-user-images",
"TenantId": "your-tenant-id"
}
}
Multi-Tenant
NAuth supports multi-tenant architectures where a single NAuth.API instance serves multiple tenants with isolated data.
How It Works
- Outgoing requests: The
TenantDelegatingHandlerautomatically injects theX-Tenant-IdHTTP header into every request made byUserClientandRoleClient. - Incoming requests: The
NAuthHandlerresolves the JWT secret per tenant by reading thetenant_idclaim from the token and delegating toITenantSecretProvider. - Fallback: If no tenant-specific secret is found, the default
JwtSecretfromNAuthSettingis used.
Option 1: Simple (Single Tenant via Settings)
Use the default SettingsTenantProvider, which reads the tenant ID from configuration:
services.Configure<NAuthSetting>(Configuration.GetSection("NAuthSetting"));
services.AddNAuth(); // Uses SettingsTenantProvider by default
services.AddNAuthAuthentication();
{
"NAuthSetting": {
"ApiUrl": "https://your-nauth-api.com/api",
"JwtSecret": "your-jwt-secret-key-min-64-characters",
"TenantId": "tenant-abc"
}
}
Option 2: Custom Tenant Provider
Implement ITenantProvider for dynamic tenant resolution (e.g., from request headers, subdomains, or route data):
using NAuth.ACL.Interfaces;
public class HeaderTenantProvider : ITenantProvider
{
private readonly IHttpContextAccessor _httpContextAccessor;
public HeaderTenantProvider(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public string? GetTenantId()
{
return _httpContextAccessor.HttpContext?
.Request.Headers["X-Tenant-Id"].FirstOrDefault();
}
}
Register with the generic overload:
services.AddHttpContextAccessor();
services.AddNAuth<HeaderTenantProvider>();
services.AddNAuthAuthentication();
Option 3: Per-Tenant JWT Secrets
Implement ITenantSecretProvider so the authentication handler can validate tokens signed with different secrets per tenant:
using NAuth.ACL.Interfaces;
public class DatabaseTenantSecretProvider : ITenantSecretProvider
{
private readonly ITenantRepository _tenantRepo;
public DatabaseTenantSecretProvider(ITenantRepository tenantRepo)
{
_tenantRepo = tenantRepo;
}
public string? GetJwtSecret(string tenantId)
{
var tenant = _tenantRepo.GetById(tenantId);
return tenant?.JwtSecret;
}
}
Register it alongside your tenant provider:
services.AddNAuth<HeaderTenantProvider>();
services.AddNAuthAuthentication();
services.AddScoped<ITenantSecretProvider, DatabaseTenantSecretProvider>();
The NAuthHandler will:
- Read the
tenant_idclaim from the JWT token (without validating first) - Call
ITenantSecretProvider.GetJwtSecret(tenantId)to get the tenant-specific secret - Validate the token using the resolved secret
- Fall back to
NAuthSetting.JwtSecretif no tenant secret is found
Core DTOs
UserInfo
Complete user information including profile, roles, addresses, and phones.
public class UserInfo
{
public long UserId { get; set; }
public string Slug { get; set; }
public string ImageUrl { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Hash { get; set; }
public bool IsAdmin { get; set; }
public DateTime? BirthDate { get; set; }
public string IdDocument { get; set; }
public string PixKey { get; set; }
public string Password { get; set; }
public int Status { get; set; }
public IList<RoleInfo> Roles { get; set; }
public IList<UserPhoneInfo> Phones { get; set; }
public IList<UserAddressInfo> Addresses { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }
}
UserInsertedInfo
Simplified model for user registration (without system-generated fields).
public class UserInsertedInfo
{
public string Slug { get; set; }
public string ImageUrl { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public bool IsAdmin { get; set; }
public DateTime? BirthDate { get; set; }
public string IdDocument { get; set; }
public string PixKey { get; set; }
public string Password { get; set; }
public IList<RoleInfo> Roles { get; set; }
public IList<UserPhoneInfo> Phones { get; set; }
public IList<UserAddressInfo> Addresses { get; set; }
}
Authentication Models
// Login credentials
public class LoginParam
{
public string Email { get; set; }
public string Password { get; set; }
}
// Authentication result with JWT token
public class UserTokenResult
{
public string Token { get; set; }
public UserInfo User { get; set; }
}
Password Management
// Change password with current password verification
public class ChangePasswordParam
{
public string OldPassword { get; set; }
public string NewPassword { get; set; }
}
// Reset password using recovery hash
public class ChangePasswordUsingHashParam
{
public string RecoveryHash { get; set; }
public string NewPassword { get; set; }
}
Role, Search and Pagination
public class RoleInfo
{
public long RoleId { get; set; }
public string Slug { get; set; }
public string Name { get; set; }
}
public class UserSearchParam
{
public string SearchTerm { get; set; }
public int Page { get; set; }
public int PageSize { get; set; }
}
public class PagedResult<T>
{
public IList<T> Items { get; set; }
public int Page { get; set; }
public int PageSize { get; set; }
public int TotalCount { get; set; }
public int TotalPages { get; }
public bool HasPreviousPage { get; }
public bool HasNextPage { get; }
}
Settings
public class NAuthSetting
{
public string ApiUrl { get; set; }
public string JwtSecret { get; set; }
public string BucketName { get; set; }
public string TenantId { get; set; }
}
User Client
IUserClient Interface
Complete user management operations:
public interface IUserClient
{
// Session Management
UserSessionInfo? GetUserInSession(HttpContext httpContext);
// User Retrieval
Task<UserInfo?> GetMeAsync(string token);
Task<UserInfo?> GetByIdAsync(long userId, string token);
Task<UserInfo?> GetByTokenAsync(string token);
Task<UserInfo?> GetByEmailAsync(string email);
Task<UserInfo?> GetBySlugAsync(string slug);
Task<IList<UserInfo>> ListAsync(int take);
// User Management
Task<UserInfo?> InsertAsync(UserInsertedInfo user);
Task<UserInfo?> UpdateAsync(UserInfo user, string token);
// Authentication
Task<UserTokenResult?> LoginWithEmailAsync(LoginParam param);
// Password Management
Task<bool> HasPasswordAsync(string token);
Task<bool> ChangePasswordAsync(ChangePasswordParam param, string token);
Task<bool> SendRecoveryMailAsync(string email);
Task<bool> ChangePasswordUsingHashAsync(ChangePasswordUsingHashParam param);
// File Upload
Task<string> UploadImageUserAsync(Stream fileStream, string fileName, string token);
}
Usage Examples
User Registration
using NAuth.ACL.Interfaces;
using NAuth.DTO.User;
public class UserService
{
private readonly IUserClient _userClient;
public UserService(IUserClient userClient)
{
_userClient = userClient;
}
public async Task<UserInfo> RegisterUserAsync()
{
var newUser = new UserInsertedInfo
{
Name = "John Doe",
Email = "john.doe@example.com",
Password = "SecureP@ssw0rd",
BirthDate = new DateTime(1990, 1, 1),
IdDocument = "12345678901",
Roles = new List<RoleInfo>
{
new RoleInfo { RoleId = 1 }
}
};
var result = await _userClient.InsertAsync(newUser);
return result;
}
}
User Login
public async Task<UserTokenResult> LoginAsync(string email, string password)
{
var loginParam = new LoginParam
{
Email = email,
Password = password
};
var result = await _userClient.LoginWithEmailAsync(loginParam);
if (result != null)
{
Console.WriteLine($"Logged in as: {result.User.Name}");
Console.WriteLine($"Token: {result.Token}");
}
return result;
}
Password Management
// Change password (authenticated user)
var changeParam = new ChangePasswordParam
{
OldPassword = "OldPassword123",
NewPassword = "NewSecureP@ssw0rd"
};
var success = await _userClient.ChangePasswordAsync(changeParam, token);
// Send recovery email
await _userClient.SendRecoveryMailAsync("user@example.com");
// Reset password using hash from email
var resetParam = new ChangePasswordUsingHashParam
{
RecoveryHash = "abc123def456",
NewPassword = "NewP@ssw0rd123"
};
await _userClient.ChangePasswordUsingHashAsync(resetParam);
Get User from Session
[ApiController]
[Route("api/[controller]")]
public class ProfileController : ControllerBase
{
private readonly IUserClient _userClient;
public ProfileController(IUserClient userClient)
{
_userClient = userClient;
}
[HttpGet]
[Authorize]
public IActionResult GetProfile()
{
var user = _userClient.GetUserInSession(HttpContext);
return user == null ? Unauthorized() : Ok(user);
}
}
Role Client
IRoleClient Interface
public interface IRoleClient
{
Task<IList<RoleInfo>> ListAsync();
Task<RoleInfo?> GetByIdAsync(long roleId);
Task<RoleInfo?> GetBySlugAsync(string slug);
}
Usage Example
using NAuth.ACL.Interfaces;
using NAuth.DTO.User;
public class RoleService
{
private readonly IRoleClient _roleClient;
public RoleService(IRoleClient roleClient)
{
_roleClient = roleClient;
}
public async Task<IList<RoleInfo>> GetAllRolesAsync()
{
return await _roleClient.ListAsync();
}
}
Authentication Handler
Custom JWT authentication handler for ASP.NET Core middleware with multi-tenant support:
[ApiController]
[Route("api/[controller]")]
public class SecureController : ControllerBase
{
[HttpGet]
[Authorize] // Uses NAuthHandler automatically
public IActionResult GetSecureData()
{
var userId = User.FindFirst("userId")?.Value;
var email = User.FindFirst(ClaimTypes.Email)?.Value;
var isAdmin = User.FindFirst("isAdmin")?.Value;
return Ok(new { UserId = userId, Email = email, IsAdmin = isAdmin });
}
[HttpGet("admin")]
[Authorize(Roles = "admin")]
public IActionResult GetAdminData()
{
return Ok("Admin only data");
}
}
JSON Serialization
All DTOs are decorated with JSON attributes for seamless serialization with both Newtonsoft.Json and System.Text.Json. The library includes NullableDateTimeConverter for proper nullable DateTime handling:
[JsonConverter(typeof(NullableDateTimeConverter))]
public DateTime? BirthDate { get; set; }
Advanced Configuration
Custom HTTP Client Configuration
services.AddHttpClient<IUserClient, UserClient>(client =>
{
client.Timeout = TimeSpan.FromSeconds(30);
client.DefaultRequestHeaders.Add("User-Agent", "MyApp/1.0");
});
Retry Policy with Polly
services.AddHttpClient<IUserClient, UserClient>()
.AddPolicyHandler(HttpPolicyExtensions
.HandleTransientHttpError()
.WaitAndRetryAsync(3, retryAttempt =>
TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))));
Error Handling
All client methods may throw exceptions. Implement proper error handling:
try
{
var user = await _userClient.GetMeAsync(token);
}
catch (HttpRequestException ex)
{
_logger.LogError(ex, "Network error occurred");
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving user");
}
Dependencies
- Newtonsoft.Json (13.0.3)
- Microsoft.AspNetCore.Authentication (2.3.0)
- Microsoft.Extensions.Configuration.Abstractions (9.0.8)
- Microsoft.Extensions.Http (9.0.8)
- System.IdentityModel.Tokens.Jwt (8.15.0)
- zTools (latest)
Best Practices
- Token Storage: Store JWT tokens securely (HttpOnly cookies or secure storage)
- Token Refresh: Implement token refresh before expiration
- Error Handling: Always wrap API calls in try-catch blocks
- Logging: Use structured logging for debugging
- Dependency Injection: Always use DI for client instances — prefer
AddNAuth()over manual registration - Configuration: Use strongly-typed configuration with
IOptions<NAuthSetting> - Multi-Tenant: Use
AddNAuth<T>()with a customITenantProviderfor dynamic tenant resolution in multi-tenant scenarios
NAuth Ecosystem
| Project | Type | Package | Description |
|---|---|---|---|
| NAuth.API | .NET | — | Central REST API backend (main project) |
| NAuth | .NET | Unified DTOs + ACL client library (this package) | |
| nauth-react | NPM | React component library (login, register, user management) |
Dependency graph
nauth-react (NPM)
└─ NAuth.API (HTTP)
└─ NAuth (NuGet - DTOs + ACL)
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Links
Support
For issues, questions, or contributions, please visit the GitHub repository.
Made with love by Rodrigo Landim Carneiro at Emagine
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- Microsoft.AspNetCore.Authentication (>= 2.3.0)
- Microsoft.Extensions.Configuration.Abstractions (>= 9.0.8)
- Microsoft.Extensions.Http (>= 9.0.8)
- Newtonsoft.Json (>= 13.0.3)
- System.IdentityModel.Tokens.Jwt (>= 8.15.0)
- zTools (>= 0.3.8)
| Version | Downloads | Last Updated |
|---|---|---|
| 0.5.10 | 36 | 4/4/2026 |
| 0.5.9 | 103 | 3/18/2026 |
| 0.5.8 | 89 | 3/18/2026 |
| 0.5.7 | 97 | 3/12/2026 |
| 0.5.6 | 87 | 3/11/2026 |
| 0.5.5 | 448 | 3/11/2026 |
| 0.5.4 | 88 | 3/11/2026 |
| 0.5.3 | 84 | 3/11/2026 |
| 0.5.2 | 125 | 3/10/2026 |
| 0.5.1 | 81 | 3/10/2026 |
| 0.5.0 | 91 | 3/10/2026 |
| 0.4.3 | 97 | 2/26/2026 |
| 0.4.2 | 112 | 2/19/2026 |
| 0.4.1 | 97 | 2/18/2026 |
| 0.4.0 | 91 | 2/18/2026 |