PrimusSaaS.Identity.Validator
1.2.2
See the version list below for details.
dotnet add package PrimusSaaS.Identity.Validator --version 1.2.2
NuGet\Install-Package PrimusSaaS.Identity.Validator -Version 1.2.2
<PackageReference Include="PrimusSaaS.Identity.Validator" Version="1.2.2" />
<PackageVersion Include="PrimusSaaS.Identity.Validator" Version="1.2.2" />
<PackageReference Include="PrimusSaaS.Identity.Validator" />
paket add PrimusSaaS.Identity.Validator --version 1.2.2
#r "nuget: PrimusSaaS.Identity.Validator, 1.2.2"
#:package PrimusSaaS.Identity.Validator@1.2.2
#addin nuget:?package=PrimusSaaS.Identity.Validator&version=1.2.2
#tool nuget:?package=PrimusSaaS.Identity.Validator&version=1.2.2
Primus SaaS Identity Validator - .NET SDK
Official .NET SDK for validating JWT/OIDC tokens from your configured identity providers (Azure AD, LocalAuth, or any JWT issuer). The package is library-only: no Primus-hosted login, no Primus-issued tokens, no outbound calls to Primus.
Installation
dotnet add package PrimusSaaS.Identity.Validator
Or via NuGet Package Manager:
Install-Package PrimusSaaS.Identity.Validator
Quick Start
1. Configure in Program.cs or Startup.cs
using PrimusSaaS.Identity.Validator;
var builder = WebApplication.CreateBuilder(args);
// Add Primus Identity validation (multi-issuer)
builder.Services.AddPrimusIdentity(options =>
{
options.Issuers = new()
{
new IssuerConfig
{
Name = "AzureAD",
Type = IssuerType.Oidc,
Issuer = "https://login.microsoftonline.com/<TENANT_ID>/v2.0",
Authority = "https://login.microsoftonline.com/<TENANT_ID>/v2.0",
Audiences = new List<string> { "api://your-api-id" }
},
new IssuerConfig
{
Name = "LocalAuth",
Type = IssuerType.Jwt,
Issuer = "https://auth.yourcompany.com",
Secret = "your-local-secret",
Audiences = new List<string> { "api://your-api-id" }
}
};
options.ValidateLifetime = true;
options.RequireHttpsMetadata = true; // Set false for local dev only
options.ClockSkew = TimeSpan.FromMinutes(5);
// Optional: map claims to tenant context
options.TenantResolver = claims => new TenantContext
{
TenantId = claims.Get("tid") ?? "default",
Roles = claims.Get<List<string>>("roles") ?? new List<string>()
};
});
builder.Services.AddAuthorization();
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
2. Protect Your API Endpoints
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using PrimusSaaS.Identity.Validator;
[ApiController]
[Route("api/[controller]")]
public class SecureController : ControllerBase
{
[HttpGet]
[Authorize] // Requires valid token from a configured issuer
public IActionResult GetSecureData()
{
// Get the authenticated Primus user
var primusUser = HttpContext.GetPrimusUser();
return Ok(new
{
message = "Secure data accessed successfully",
user = new
{
userId = primusUser?.UserId,
email = primusUser?.Email,
name = primusUser?.Name,
roles = primusUser?.Roles
}
});
}
[HttpGet("admin")]
[Authorize(Roles = "Admin")] // Requires Admin role from your IdP
public IActionResult GetAdminData()
{
return Ok(new { message = "Admin-only data" });
}
}
3. Access User Information
// In any controller or middleware
var primusUser = HttpContext.GetPrimusUser();
if (primusUser != null)
{
Console.WriteLine($"User ID: {primusUser.UserId}");
Console.WriteLine($"Email: {primusUser.Email}");
Console.WriteLine($"Name: {primusUser.Name}");
Console.WriteLine($"Roles: {string.Join(", ", primusUser.Roles)}");
// Access additional claims
foreach (var claim in primusUser.AdditionalClaims)
{
Console.WriteLine($"{claim.Key}: {claim.Value}");
}
}
Configuration Options
| Option | Required | Description | Default |
|---|---|---|---|
| Issuers | Yes | List of issuer configs (Oidc or Jwt) | - |
| ValidateLifetime | No | Validate token expiration | true |
| RequireHttpsMetadata | No | Require HTTPS for metadata | true |
| ClockSkew | No | Allowed time difference | 5 minutes |
| JwksCacheTtl | No | JWKS cache TTL (OIDC) | 24 hours |
| TenantResolver | No | Map claims to TenantContext | null |
IssuerConfig
| Field | Required | Description |
|---|---|---|
| Name | Yes | Friendly name (e.g., AzureAD, LocalAuth) |
| Type | Yes | Oidc or Jwt |
| Issuer | Yes | Expected iss value to route tokens |
| Authority | OIDC only | Authority URL for discovery/JWKS |
| JwksUrl | JWT optional | JWKS endpoint (if not using Secret) |
| Secret | JWT optional | Symmetric key for HMAC tokens |
| Audiences | Yes | Allowed audience values |
Configuration from appsettings.json
{
"PrimusIdentity": {
"Issuers": [
{
"Name": "AzureAD",
"Type": "Oidc",
"Issuer": "https://login.microsoftonline.com/<TENANT_ID>/v2.0",
"Authority": "https://login.microsoftonline.com/<TENANT_ID>/v2.0",
"Audiences": [ "api://your-api-id" ]
},
{
"Name": "LocalAuth",
"Type": "Jwt",
"Issuer": "https://auth.yourcompany.com",
"Secret": "your-local-secret",
"Audiences": [ "api://your-api-id" ]
}
],
"RequireHttpsMetadata": false
}
}
Generating Tokens for Local JWT Issuer
Important: The Secret, Issuer, and Audience values used when generating tokens MUST EXACTLY MATCH your validator configuration.
Quick Example
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Microsoft.IdentityModel.Tokens;
public string GenerateLocalJwtToken(string userId, string email, string name)
{
// Critical: Load from same configuration source
var secret = _config["PrimusIdentity:Issuers:1:Secret"];
var issuer = _config["PrimusIdentity:Issuers:1:Issuer"];
var audience = _config["PrimusIdentity:Issuers:1:Audiences:0"];
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.UTF8.GetBytes(secret);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[]
{
new Claim("sub", userId),
new Claim("email", email),
new Claim("name", name)
}),
Expires = DateTime.UtcNow.AddHours(1),
Issuer = issuer,
Audience = audience,
SigningCredentials = new SigningCredentials(
new SymmetricSecurityKey(key),
SecurityAlgorithms.HmacSha256Signature
)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
For complete token generation examples, see TOKEN_GENERATION_GUIDE.md
Troubleshooting
Common Errors
| Error | Cause | Solution |
|---|---|---|
| Invalid signature | Secret key mismatch | Ensure token generation and validation use the same secret |
| Untrusted issuer | Issuer format incorrect | Use full URL format (e.g., https://localhost:5265) not name |
| Invalid audience | Audience mismatch | Use API identifier format (e.g., api://your-app-id) |
| Token expired | Token past expiration | Generate new token or increase ClockSkew |
For detailed troubleshooting, see ERROR_REFERENCE.md
Production Deployment
Caution: Never commit secrets to source control! Use Azure Key Vault or environment variables.
Quick Checklist
- Secrets stored in Azure Key Vault
- RequireHttpsMetadata: true in production
- HTTPS redirection enabled
- CORS configured for production domains
- Logging and monitoring configured
For complete deployment guide, see PRODUCTION_DEPLOYMENT.md
Client Usage Example
To call your protected API from a client application:
using System.Net.Http.Headers;
var httpClient = new HttpClient();
var jwtToken = "your-jwt-token-here"; // From your auth system or token generator
// Add token to Authorization header
httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", jwtToken);
var response = await httpClient.GetAsync("https://your-api.com/api/secure");
var data = await response.Content.ReadAsStringAsync();
Development Tips
Disable HTTPS Requirement for Local Development
builder.Services.AddPrimusIdentity(options =>
{
options.RequireHttpsMetadata = false; // Allow HTTP in development
// ... other options
});
Enable Detailed Logging
The SDK automatically logs authentication events to the console. For more detailed logging, enable ASP.NET Core logging:
{
"Logging": {
"LogLevel": {
"Microsoft.AspNetCore.Authentication": "Debug"
}
}
}
Requirements
- .NET 7.0 or later
- ASP.NET Core 7.0 or later
Known Issues
Namespace Conflict with PrimusSaaS.Logging
If you are using both PrimusSaaS.Identity.Validator and PrimusSaaS.Logging, you may encounter an ambiguous reference error for UsePrimusLogging().
Solution: Use the fully qualified name or an alias.
using PrimusLogging = PrimusSaaS.Logging.Extensions;
// ...
PrimusLogging.LoggingExtensions.UsePrimusLogging(app);
Documentation
- TOKEN_GENERATION_GUIDE.md - Complete guide to generating JWT tokens
- LOCAL_DEVELOPMENT_GUIDE.md - Setup guide for offline/local development
- INTEGRATION_PATTERNS.md - Controller, Service, and Middleware examples
- TENANT_RESOLVER_GUIDE.md - Multi-tenant context resolution guide
- PRIMUS_USER_REFERENCE.md - PrimusUser object properties and mapping
- ERROR_HANDLING_GUIDE.md - Handling exceptions and customizing responses
- ERROR_REFERENCE.md - Troubleshooting validation errors
- PRODUCTION_DEPLOYMENT.md - Production deployment best practices
- SECRET_MANAGEMENT.md - Securely managing secrets (Key Vault, User Secrets)
- TESTING_GUIDE.md - Testing guide with Postman & Integration Tests
- CLAIMS_MAPPING.md - Reference for required and optional claims
- ANGULAR_INTEGRATION.md - Integration guide for Angular applications
Support
For issues, questions, or contributions, visit:
- GitHub: https://github.com/primus-saas/identity-validator
- Documentation: https://docs.primus-saas.com
License
MIT License - see LICENSE file for details
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net7.0 is compatible. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. 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. |
-
net7.0
- Microsoft.AspNetCore.Authentication.JwtBearer (>= 7.0.20)
- Microsoft.Extensions.Options (>= 10.0.0)
- System.IdentityModel.Tokens.Jwt (>= 8.14.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.0.0 | 107 | 1/12/2026 |
| 1.5.0 | 313 | 12/3/2025 |
| 1.3.6 | 274 | 11/30/2025 |
| 1.3.5 | 234 | 11/30/2025 |
| 1.3.3 | 239 | 11/29/2025 |
| 1.3.2 | 126 | 11/29/2025 |
| 1.3.1 | 137 | 11/28/2025 |
| 1.3.0 | 206 | 11/24/2025 |
| 1.2.3 | 200 | 11/24/2025 |
| 1.2.2 | 200 | 11/24/2025 |
| 1.2.1 | 197 | 11/24/2025 |
| 1.2.0 | 190 | 11/23/2025 |
| 1.1.0 | 158 | 11/23/2025 |
| 1.0.0 | 317 | 11/21/2025 |