LevelUp.Health.Auth 0.1.0

There is a newer prerelease version of this package available.
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
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="LevelUp.Health.Auth" Version="0.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="LevelUp.Health.Auth" Version="0.1.0" />
                    
Directory.Packages.props
<PackageReference Include="LevelUp.Health.Auth" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add LevelUp.Health.Auth --version 0.1.0
                    
#r "nuget: LevelUp.Health.Auth, 0.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package LevelUp.Health.Auth@0.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=LevelUp.Health.Auth&version=0.1.0
                    
Install as a Cake Addin
#tool nuget:?package=LevelUp.Health.Auth&version=0.1.0
                    
Install as a Cake Tool

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 (section AuthHardening) 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 problem type link base.
  • ApiKeySettings (section ApiKeys) — the valid-key set the validator loads. Keys are hashed (HMAC-SHA256, keyed by a shared pepper in ApiKeyHashingOptions) rather than compared as plaintext, and the digest set is rebuilt live via IOptionsMonitor on config reload.
  • Admin privilege is no longer an AuthHardeningOptions field. It is gated by a wholly separate, fail-secure store — AdminApiKeySettings (section AdminApiKeys) validated by IAdminApiKeyValidator / AdminApiKeyValidator — so a key present only in ApiKeySettings can never satisfy an admin check, and an unconfigured admin store rejects every admin request.
  • IResourceOwnershipResolver is the ownership port behind ResourceOwnershipFilter (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 own IResourceOwnershipResolver.
  • No Roles constants. RoleRequirementFilter / ResourceOwnershipFilter take 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).
  • RoleRequirementFilter is 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.
  • ApiKeyValidator rejects unknown and blank keys, comparing HMAC-hashed digests rather than plaintext.
  • AdminApiKeyValidator is fail-secure — with no admin keys configured, every admin request is rejected (no special-case bypass).
  • ResourceOwnershipFilter is fail-closed — a missing role, requested id, or caller id denies access.
Product 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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