LevelUp.Health.Auth
0.1.0
See the version list below for details.
dotnet add package LevelUp.Health.Auth --version 0.1.0
NuGet\Install-Package LevelUp.Health.Auth -Version 0.1.0
<PackageReference Include="LevelUp.Health.Auth" Version="0.1.0" />
<PackageVersion Include="LevelUp.Health.Auth" Version="0.1.0" />
<PackageReference Include="LevelUp.Health.Auth" />
paket add LevelUp.Health.Auth --version 0.1.0
#r "nuget: LevelUp.Health.Auth, 0.1.0"
#:package LevelUp.Health.Auth@0.1.0
#addin nuget:?package=LevelUp.Health.Auth&version=0.1.0
#tool nuget:?package=LevelUp.Health.Auth&version=0.1.0
LevelUp.Health.Auth
Role / API-key / JWT auth-hardening for the LevelUp.Health backend packages (the asclepius P2 plane).
Lifted faithfully from ares-elite/aegis-api's Aegis.API authorization, middleware, and JWT-hardening skeleton, with every Ares-specific string promoted to a configurable option and the patient-ownership rule generalized to a pluggable port.
This package is Result-free — it does not depend on LevelUp.Health.Abstractions.
It composes onto LevelUp.ServiceDefaults* at the host (it ships no ServiceDefaults, AppHost, or god-method).
What's here
| Namespace | Types |
|---|---|
LevelUp.Health.Auth.Authorization |
IApiKeyValidator / ApiKeyValidator (HMAC-hashed key validation), IAdminApiKeyValidator / AdminApiKeyValidator (distinct admin-key store), CallerContext (JWT-vs-header trust policy), RoleRequirementFilter, ResourceOwnershipFilter, IResourceOwnershipResolver + SelfReadResourceOwnershipResolver, RoleAuthorizationExtensions (RequireRole / RequireResourceOwnership) |
LevelUp.Health.Auth.Middleware |
ApiKeyAuthenticationFilter, AdminApiKeyAuthenticationFilter |
LevelUp.Health.Auth.Extensions |
JwtHardeningExtensions.AddJwtHardening(), HealthAuthServiceCollectionExtensions.AddHealthAuth() |
LevelUp.Health.Auth.Configuration |
ApiKeySettings, ApiKeyHashingOptions, AdminApiKeySettings, AuthHardeningOptions |
LevelUp.Health.Auth.OpenApi |
ApiKeySecuritySchemeTransformer.AddEndpointsHttpSecuritySchemeResolution() |
Consuming
builder.Services.AddHealthAuth(builder.Configuration); // ApiKeySettings + AuthHardeningOptions + validator + CallerContext + default resolver + filters
builder.Services.AddJwtHardening(); // 2-min clock skew, audience/issuer/lifetime validation
// Role-gated group (consumer supplies its own role strings — no fixed vocabulary ships):
var admin = app.MapGroup("/api/v1/admin").RequireRole("admin");
// Resource-ownership group: unscoped roles read anything; everyone else reads only what they own.
var history = app.MapGroup("/api/v1/history").RequireResourceOwnership("admin", "doctor", "trainer");
Seams (Ares coupling → option/port)
AuthHardeningOptions(sectionAuthHardening) parameterizes the request shape, each value defaulting to the original Ares string:- headers —
RoleHeaderName(X-User-Role),OwnedResourceIdHeaderName(X-User-Patient-Fhir-Id),ApiKeyHeaderName(X-API-Key),AdminApiKeyHeaderName(X-Admin-API-Key); - claims —
RoleClaimType(role),OwnedResourceIdClaimType(patient_fhir_id); ErrorTypeBaseUri(https://api.aegis.areselite.com/errors/) — the RFC 7807 problemtypelink base.
- headers —
ApiKeySettings(sectionApiKeys) — the valid-key set the validator loads. Keys are hashed (HMAC-SHA256, keyed by a shared pepper inApiKeyHashingOptions) rather than compared as plaintext, and the digest set is rebuilt live viaIOptionsMonitoron config reload.- Admin privilege is no longer an
AuthHardeningOptionsfield. It is gated by a wholly separate, fail-secure store —AdminApiKeySettings(sectionAdminApiKeys) validated byIAdminApiKeyValidator/AdminApiKeyValidator— so a key present only inApiKeySettingscan never satisfy an admin check, and an unconfigured admin store rejects every admin request. IResourceOwnershipResolveris the ownership port behindResourceOwnershipFilter(replacing Ares'PatientSelfReadFilter). The shipped default,SelfReadResourceOwnershipResolver, allows a read when the requested resource id equals the caller's own id (URL-decoded, ordinal, fail-closed). Ares' patient/Person.link-graph specifics are not shipped — a consumer needing graph-based ownership registers its ownIResourceOwnershipResolver.- No
Rolesconstants.RoleRequirementFilter/ResourceOwnershipFiltertake consumer-supplied role strings; the Ares clinical role vocabulary (doctor/athlete/client_admin/…) does not ship (spec R5.3).
Security guarantees (kill-probe-validated)
- JWT hardening is verbatim —
ClockSkew = 2 min,ValidateAudience/ValidateIssuer/ValidateLifetime = true(spec R5.2). RoleRequirementFilteris fail-closed and gives JWT claim precedence over the trusted header — an authenticated JWT with no/insufficient role is denied even when a spoofed role header is present.ApiKeyValidatorrejects unknown and blank keys, comparing HMAC-hashed digests rather than plaintext.AdminApiKeyValidatoris fail-secure — with no admin keys configured, every admin request is rejected (no special-case bypass).ResourceOwnershipFilteris fail-closed — a missing role, requested id, or caller id denies access.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. 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. |
-
net10.0
- Microsoft.AspNetCore.OpenApi (>= 10.0.9)
- Microsoft.Identity.Web (>= 4.13.0)
- Microsoft.OpenApi (>= 2.7.5)
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 |
|---|---|---|
| 0.3.0-preview.1 | 80 | 8/14/2026 |
| 0.2.0-rc.1 | 1,239 | 8/20/2026 |
| 0.2.0-preview.3 | 72 | 8/18/2026 |
| 0.2.0-preview.2 | 79 | 8/14/2026 |
| 0.2.0-preview.1 | 81 | 8/14/2026 |
| 0.1.0 | 731 | 7/17/2026 |
| 0.1.0-rc.1 | 138 | 7/15/2026 |
| 0.1.0-preview.2 | 79 | 7/10/2026 |
| 0.1.0-preview.1 | 154 | 6/26/2026 |