Winglet.Authentication
0.1.6
dotnet add package Winglet.Authentication --version 0.1.6
NuGet\Install-Package Winglet.Authentication -Version 0.1.6
<PackageReference Include="Winglet.Authentication" Version="0.1.6" />
<PackageVersion Include="Winglet.Authentication" Version="0.1.6" />
<PackageReference Include="Winglet.Authentication" />
paket add Winglet.Authentication --version 0.1.6
#r "nuget: Winglet.Authentication, 0.1.6"
#:package Winglet.Authentication@0.1.6
#addin nuget:?package=Winglet.Authentication&version=0.1.6
#tool nuget:?package=Winglet.Authentication&version=0.1.6
Winglet.Authentication
Winglet.Authentication is the shared integration boundary between native ASP.NET Core JWT Bearer validation and the immutable Winglet request context. ASP.NET Core / IdentityModel owns bearer extraction, signature, issuer, lifetime, key and clock-skew validation; this package adds the fixed canonical JWT v1 profile checks and establishes trusted TenantContext.
The application-facing context keeps Identity, Session, Service caller, Tenant, Authentication, actor and authorization snapshots separate. Global-context tokens have no tenant. Tenant-context tokens contain exactly one tenant and only that tenant's broad authorization snapshot. Service-only and on-behalf-of tokens preserve caller/actor distinction.
Register the package with AddWingletAuthentication(configuration), run UseAuthentication() first, then UseWingletAuthenticationContext(). Add AddWingletAuthorization() when using the supplied privilege, assurance, freshness or tenant-context policy handlers. The package never trusts tenant values from request body, query or headers and never exposes raw claims as the primary API.
Use RequireWingletPrivilege("event.manage"), RequireWingletAuthenticationAssurance(WingletAuthenticationAssurance.Strong), RequireWingletAuthenticationFreshness(...) and RequireWingletTenantContext() in normal ASP.NET Core policies. Canonical privilege matching is centralized; roles and groups are not the application authorization API.
Canonical wire details are defined by docs/contracts/authentication/jwt-v1.md. The canonical profile requires winglet+jwt, RS256, an opaque kid, exact configured issuer, exp, iat, 60-second clock skew, canonical claim types and explicit global/tenant context. No per-request Identity/Auth lookup is performed.
Outbound IWingletClientTokenProvider integration is implemented by WingletAuthenticationTokenProvider. It validates operation-declared global/tenant and service-only/on-behalf-of semantics against the trusted current context, then delegates to IWingletAuthenticationTokenAcquirer. Register the canonical Identity-backed implementation with AddWingletAuthenticationTokenAcquisition(configuration) when the host uses outbound service credentials. Configuration uses the standard IdentityTokenAcquisition section:
{
"IdentityTokenAcquisition": {
"IdentityBaseAddress": "https://identity.internal/",
"ServiceId": "winglet.example",
"Credential": "provided-by-the-host-secret-provider",
"RefreshBeforeExpiry": "00:00:30"
}
}
IdentityBaseAddress, ServiceId, and Credential are required. IdentityBaseAddress must be an absolute URI without user information, query, or fragment. Supply Credential through the host's normal secret/configuration provider; do not commit service credentials. Registration validates the options at startup and uses a named HttpClient. ServiceOnly Global and Tenant requests use Identity's POST /api/v1/service-tokens contract. Target-bound service_authentication uses POST /api/v1/service-authentication, with the requested target service as the audience. HTTP errors and cancellation are preserved, and malformed or context-mismatched success responses are rejected. No JWT is constructed locally and inbound bearer credentials are never forwarded.
Identity endpoints must use HTTPS by default. Local HTTP is accepted only when AllowHttpForLocalDevelopment is explicitly true, the host environment is Development, and the endpoint is a loopback URI such as http://localhost:5000/. Production and non-loopback HTTP endpoints fail closed even when the opt-in is set. Do not enable this option outside local development.
The production acquirer caches tokens until their expiry enters the configured refresh window (30 seconds by default), with a 1,024-entry bound. Cache identity includes Identity endpoint, configured service identity, a one-way hash of the current credential, acquisition mode, scope, tenant ID for tenant scope, and target service/audience. Tenant A and tenant B therefore cannot share cached tokens. A per-key asynchronous lock prevents duplicate concurrent refreshes; failures are not cached. IOptionsMonitor observes host configuration reloads: a changed credential gets a distinct cache identity and the old credential is no longer used for new acquisitions. There is no independent secret watcher; reload behavior is owned by the host's configuration provider. Hosts that intentionally provide their own implementation can register IWingletAuthenticationTokenAcquirer before calling the opt-in registration; test and custom implementations remain supported.
The current Identity service contract has no on-behalf-of service-credential issuance endpoint. The production acquirer fails closed for OBO rather than turning it into ServiceOnly or forwarding the inbound bearer. OBO remains available through a host-supplied acquirer that implements an explicitly supported Identity contract; adding that contract requires an Identity-side decision and implementation.
Tenant-scoped ServiceOnly calls can also run in a background worker without an inbound request or Actor. The worker must create a fresh DI scope for each tenant-owned work item, obtain TenantId from trusted durable work state, enter it through ITenantContextScopeFactory.BeginScope(TenantId), make outbound calls while that scope is active, and dispose the tenant scope normally. ITenantContextScopeFactory.BeginScope establishes execution context; it is not an authorization check. The outbound token provider allows an execution-scope tenant to select a tenant token only in a true no-HTTP execution with no request context. An inbound HTTP request must use its authenticated tenant context; a global, anonymous, or missing request tenant cannot fall back to an execution-scope tenant. Do not copy tenant IDs from arbitrary HTTP headers, body fields, or query parameters into a trusted background scope. Authorization remains the target service's responsibility.
When an authenticated request tenant and the active Winglet tenant context are both present, outbound tenant token acquisition requires them to match. Background ServiceOnly/Tenant acquisition does not create an Actor or synthetic request context. OBO still requires the authenticated request Actor, and ServiceOnly/Global plus service_authentication remain global flows. The tenant context and scope lifetime rules are owned by Winglet.Tenancy.
Winglet.Identity and Winglet.Auth are currently .NET services. Identity issues user tokens with the canonical typ=winglet+jwt header and RS256 signing, and publishes the public signing key through its JWKS endpoint; Auth owns authorization data and effective-privilege snapshots, which Identity reads when issuing tokens. Identity also has a separate, optional HS256 legacy-token output path. That legacy format is not the canonical JWT v1 profile and is not accepted as a modern token.
The current Identity implementation and the canonical JWT v1 contract are not fully aligned: for example, Identity currently writes its GUID session ID to sid, while the contract specifies the decimal form of a canonical numeric session ID. The canonical validator checks that sid is a non-empty string but does not enforce the contract's decimal numeric semantics. Treat this as an unresolved wire-compatibility difference; this documentation update does not change either runtime behavior or the normative contract. See the JWT v1 contract's current-implementation status section for the observed details.
| 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.Authentication.JwtBearer (>= 10.0.11)
- Microsoft.Extensions.Http (>= 10.0.11)
- Winglet.Client (>= 0.2.1)
- Winglet.Tenancy (>= 0.1.0)
NuGet packages (3)
Showing the top 3 NuGet packages that depend on Winglet.Authentication:
| Package | Downloads |
|---|---|
|
Winglet.Authentication.Testing
Test-only ephemeral canonical Winglet JWT v1 issuer and ASP.NET Core host integration. |
|
|
Winglet.Tenancy.Lifecycle.Server
Thin ASP.NET Core integration for the Winglet.NET tenant lifecycle protocol. |
|
|
Winglet.ResourceAuthorization.Client
Typed Winglet.NET resource authorization client with bounded local decision cache. |
GitHub repositories
This package is not used by any popular GitHub repositories.