OrderService has been open since Post 1. Any process with network access can POST to /orders/create. On a developer’s laptop, that is acceptable. In a staging environment, it is not — and in production, it is a critical security gap. Phase 4 closes it.
Post 20 adds JWT bearer authentication to OrderService. Unprotected POST to /orders/create → 401 Unauthorized. POST with a valid Authorization: Bearer {token} header → 200, message published to Service Bus. The token is issued by a new /auth/token test endpoint in UserService — a stand-in for the Azure AD token issuance that happens in production.
Two packages, one configuration change, two source files. The local development path uses a symmetric HMAC-SHA256 signing key in appsettings.Development.json. The production path replaces four lines with Microsoft.Identity.Web and an AzureAd configuration section — no code change, no new package, no subscription required to build and test it locally.
Career skill this post adds: JWT bearer authentication in ASP.NET Core 8 Minimal APIs —
builder.Services.AddAuthentication().AddJwtBearer(),app.UseAuthentication(),.RequireAuthorization(). The OTel event hooks that propagate claim values to the Aspire Dashboard trace are the production debugging pattern that turns a 401 from “unknown failure” to “specific validation error in the span.” Appears on every Azure .NET senior role that lists API security alongside observability.
JWT structure — header, claims payload, signature — and what
[Authorize]verifiesAddAuthentication().AddJwtBearer()— the three-line middleware registrationTokenValidationParameters— the six properties and what each doesLocal symmetric key → production OIDC discovery — the one-section configuration swap
OTel event hooks on
OnAuthenticationFailedandOnTokenValidated.RequireAuthorization()vs.AllowAnonymous()— selective endpoint protection
System state: where we are
Phase 3 is complete. OrderService has Service Bus publishing, Event Hubs dual-streaming, Blob Storage writes, Table Storage config lookups, full App Insights telemetry, and zero authentication. Post 20 adds the security layer without changing any of the messaging or storage code.
Starting point:
git checkout post/20-jwt-authRun.\verify.ps1— all 43 Phase 1–3 checks must pass. Important:verify.ps1checks 17–29 now fetch a token from/auth/tokenbefore calling/orders/create. If/auth/tokenfails, those checks will fail. ConfirmUserServiceis healthy before running the full suite.




