Identity Envelope Middleware

What

UseIdentityEnvelopeAuthentication() is a shared ASP.NET Core middleware that reads gateway-signed identity envelope headers and hydrates HttpContext.User with the enclosed claims. It lives in StellaOps.Router.AspNet and is consumed by every downstream microservice that receives proxied requests from the Router gateway.

Why

When the Router gateway forwards a request via YARP ReverseProxy, it strips the original Authorization: Bearer <jwt> header. Instead, it signs the authenticated user’s identity into two custom headers:

Downstream services need a way to recover the caller’s identity from these headers without each service re-implementing the same verification logic. The shared middleware eliminates duplication and ensures consistent claim mapping everywhere.

How to use

In the service’s Program.cs, register the middleware before UseAuthentication():

using StellaOps.Router.AspNet;

// ...

app.UseIdentityEnvelopeAuthentication();   // <-- must come first
app.UseAuthentication();
app.UseAuthorization();

The service’s .csproj must reference StellaOps.Router.AspNet (which transitively brings in StellaOps.Router.Common containing the codec).

Configuration

The middleware reads the HMAC-SHA256 signing key from one of two sources (first wins):

SourceKey
IConfigurationRouter:IdentityEnvelopeSigningKey
Environment variableSTELLAOPS_IDENTITY_ENVELOPE_SIGNING_KEY

In the docker-compose environment the key is injected via x-router-microservice-defaults so all services share the same value automatically.

Claim mapping

When a valid, non-expired envelope is verified, the middleware creates a ClaimsPrincipal with authentication type StellaRouterEnvelope and the following claims:

Claim typeSource
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifierenvelope.Subject
subenvelope.Subject
stellaops:tenantenvelope.Tenant
tenantenvelope.Tenant
stellaops:projectenvelope.Project
projectenvelope.Project
scope (one per scope)envelope.Scopes
http://schemas.microsoft.com/ws/2008/06/identity/claims/role (one per role)envelope.Roles
<custom claim type> (one per value)envelope.Claims

envelope.Claims is the gateway-validated, non-scope claim bag used for downstream ABAC decisions. It is the only supported way for routed services to receive resource constraints such as developer-owned serviceIds, allowed environmentIds, maxEnvironmentType, and directUpdateAllowed; client-supplied claim headers are stripped before the envelope is created.

Architecture flow

Browser
  |
  |  Authorization: Bearer <jwt>
  v
Gateway (StellaOps.Gateway.WebService)
  |  1. Validates JWT
  |  2. Signs identity into envelope headers (HMAC-SHA256)
  |  3. Strips Authorization header
  |  4. Forwards via YARP ReverseProxy
  v
Downstream Service (Scanner, JobEngine, Timeline, Integrations, Concelier, ...)
  |  UseIdentityEnvelopeAuthentication()
  |  1. Reads X-StellaOps-Identity-Envelope + Signature headers
  |  2. Verifies HMAC-SHA256 signature
  |  3. Checks clock skew (5 min tolerance)
  |  4. Hydrates HttpContext.User
  v
  UseAuthentication() / UseAuthorization()
  (standard ASP.NET pipeline continues with the hydrated principal)

Error handling

The middleware never throws. All failures (missing headers, missing key, bad signature, expired envelope) are logged at Warning level under the StellaOps.IdentityEnvelope logger category. The request continues unauthenticated, allowing the standard JWT bearer handler to attempt authentication normally.

Adopted services

ServiceFile
Conceliersrc/Concelier/StellaOps.Concelier.WebService/Program.cs
Scannersrc/Scanner/StellaOps.Scanner.WebService/Program.cs
JobEnginesrc/JobEngine/StellaOps.JobEngine/StellaOps.JobEngine.WebService/Program.cs
Timelinesrc/Timeline/StellaOps.Timeline.WebService/Program.cs
Integrationssrc/Integrations/StellaOps.Integrations.WebService/Program.cs

Source