Local JWT Authentication
Integration Guide
Step 1: Install the package
dotnet add package PrimusSaaS.Identity.Validator
Step 2: Configure appsettings.json
Add this section to your appsettings.json:
{
"PrimusIdentity": {
"RequireHttpsMetadata": false,
"ValidateLifetime": true,
"ClockSkew": "00:05:00",
"Issuers": [
{
"Name": "LocalDev",
"Type": "Jwt",
"Issuer": "http://localhost:5001",
"Secret": "your-32-character-minimum-secret-key-here-change-this-in-production",
"Audiences": [ "api://local-dev" ]
}
]
}
}
What each field means
Top-level fields (full reference in the Overview):
| Key | Type | Required | Default | What it does |
|---|---|---|---|---|
RequireHttpsMetadata | bool | No | true | Set to false so the app accepts plain http:// locally. Change to true before deploying. |
ValidateLifetime | bool | No | true | Rejects tokens that have expired. Keep true unless debugging a time-related issue. |
ClockSkew | string | No | "00:05:00" | How much clock drift is tolerated between your machine and the token's expiry time. "HH:MM:SS" format. 5 minutes is a safe default. |
Issuer fields for Local JWT (Type: "Jwt"):
| Key | Type | Required | What it does |
|---|---|---|---|
Name | string | Yes | A label for this issuer — shows up in logs and error messages only. |
Type | string | Yes | Must be "Jwt" for local HMAC tokens. Other valid values: AzureAd, Auth0, Okta, Cognito, Google, GitHub. |
Issuer | string | Yes | The iss claim expected in incoming tokens. Must exactly match the URL you use when generating tokens — a trailing slash difference will cause a 401. |
Secret | string | Yes | HMAC-SHA256 signing key. Minimum 32 characters. Must be identical in both your config and your token generator. Use an environment variable or .NET User Secrets in production — never commit a real secret. |
Audiences | string[] | Yes | The aud claim(s) expected in incoming tokens. A token must match at least one entry. You choose the value — it just has to be the same in both config and token. |
Step 3: Update Program.cs
This is everything — no extra files needed.
using PrimusSaaS.Identity.Validator;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddPrimusIdentity(opts =>
builder.Configuration.GetSection("PrimusIdentity").Bind(opts));
builder.Services.AddAuthorization();
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
// Protected endpoint — returns 401 if no valid JWT is present
app.MapGet("/local", () => Results.Ok(new { validated = true }))
.RequireAuthorization();
app.Run();
That's it
No controller file. No extra class. The endpoint lives right here in Program.cs.
Step 4: Get a token and test
Use the values from your appsettings.json to generate a real signed token right here in the browser:
Run the app:
dotnet run --urls "http://localhost:5001"
Call the protected endpoint (paste the token from above):
$token = "PASTE_YOUR_TOKEN_HERE"
Invoke-RestMethod "http://localhost:5001/local" -Headers @{ Authorization = "Bearer $token" }
Expected: { "validated": true }
Confirm it blocks unauthenticated requests:
try { Invoke-RestMethod "http://localhost:5001/local" } catch { $_.Exception.Response.StatusCode }
Expected: Unauthorized