ITLab.Template.DevPack.Middleware
Provides ASP.NET Core middleware for culture negotiation, 404 handling, unauthenticated request fallback, identity bridging and domain-based tenant resolution.
Componentes
| Tipo | Nome | Responsabilidade |
|---|---|---|
| Class | CultureMiddleware | Sets request culture from the Accept-Language header (fallback: en-US) |
| Sealed Class | DevPackIdentityContextMiddleware | Bridges HttpContext.User claims into AsyncLocalCurrentUserAccessor so ICurrentUser consumers see the authenticated user |
| Sealed Class | TenantResolutionMiddleware | Resolves the tenant from the request host and cross-checks it against the token tenant (opt-in via MultiTenancyOptions.EnableDomainValidation) |
| Class | NotFoundMiddleware | Intercepts 404 responses and returns a structured error payload |
| Class | UnauthenticatedFallbackMiddleware | Returns 401 Unauthorized for requests that reach the pipeline without an identity |
Como usar
// Register middleware in the correct pipeline order.
app.UseMiddleware<CultureMiddleware>();
app.UseAuthentication();
app.UseDevPackIdentityContext(); // bridge HttpContext.User → AsyncLocal
app.UseMiddleware<UnauthenticatedFallbackMiddleware>();
app.UseAuthorization();
app.UseMiddleware<NotFoundMiddleware>();
Order matters: UseAuthentication populates HttpContext.User; UseDevPackIdentityContext projects the claims into AsyncLocalCurrentUserAccessor (consumed by RoleBasedPermissionEvaluator and other ICurrentUser consumers); UseAuthorization then evaluates policies. Without the bridge, ICurrentUser.UserRoles is empty in production → 403 on every protected endpoint.
Domain tenant resolution (TenantResolutionMiddleware)
When the host name itself carries tenant identity (acme.app.example.com → "acme"), register UseDevPackTenantResolution() after the identity bridge and before UseAuthorization:
app.UseAuthentication();
app.UseDevPackIdentityContext(); // token tenant → ICurrentUser.TenantId
app.UseDevPackTenantResolution(); // resolve host tenant + cross-check vs token
app.UseAuthorization();
The middleware is a no-op unless MultiTenancyOptions.EnableDomainValidation is true. When enabled, it resolves the host tenant via ITenantResolver, maps it to an id and validates membership through the consumer-implemented ITenantAccessValidator, then cross-checks that id against ICurrentUser.TenantId (the token tenant) — a token issued for tenant A replayed against tenant B's host is rejected. Status codes: 401 (no token tenant / unresolvable host / host-vs-token mismatch), 404 (host maps to no tenant), 403 (user has no membership). Anonymous requests and MultiTenancyOptions.ExcludedPaths pass through. The ordering after the bridge is essential — the cross-check needs the token tenant already on ICurrentUser.
O que não fazer
- Do not place
CultureMiddlewareafterUseRouting— culture must be set before route handlers execute. - Do not use
UnauthenticatedFallbackMiddlewareas a substitute for proper[Authorize]annotations. - Do not register
UseDevPackTenantResolution()beforeUseDevPackIdentityContext()— the cross-check readsICurrentUser.TenantId, which the bridge populates. Wrong order silently skips the check (token tenant always0). - Do not forget
IHttpContextAccessorwhen enabling domain resolution —DomainTenantResolveContributorresolves the request through it.
Extensão pelo produto
- Products can extend
NotFoundMiddlewareto include product-specific 404 response bodies. - Products can extend
CultureMiddlewareto resolve culture from user profile settings instead of the request header.