MILTON.ServiceDefaults

MILTON.ServiceDefaults is the standard .NET Aspire boilerplate, aggressively enhanced to encapsulate all cross-cutting concerns for the MILTON distributed application. It is applied recursively into the Program.cs bootstrapping of every individual service.

Architectural Intent

The goal of MILTON.ServiceDefaults is to guarantee that every node in the MILTON ecosystem operates with the exact same observability, health, resilience, and internal security baseline. By centralizing this configuration, we prevent configuration drift across microservices and reduce boilerplate in the application hosts.

Core Capabilities

1. Aspire Wiring & Observability (Extensions.cs)

The core AddServiceDefaults extension orchestrates:

  • OpenTelemetry & Tracing: Instruments ASP.NET Core, HTTP clients, and runtime metrics, exporting telemetry via OTLP. This ensures distributed traces flow seamlessly across the API, Notification Service, and Document Generators.
  • Health & Liveness Checks: Maps standard /health and /alive endpoints, allowing the Aspire AppHost (and eventually Kubernetes) to monitor service lifecycles.
  • Resilience: Configures HTTP client defaults with standard retries, circuit breakers, and aggressive timeouts (e.g., 10-minute timeouts suitable for long-running AI operations).
  • Service Discovery: Enables zero-configuration routing using Aspire’s service discovery mechanism.

2. Internal Identity & Edge Security

MILTON uses the Backend-For-Frontend (BFF) pattern. The MILTON.ReverseProxy (YARP Gateway) is the only component exposed to the internet. It handles OAuth/OIDC termination with Keycloak and proxies requests to downstream services.

To securely pass the authenticated user’s identity to the internal network without requiring downstream services to re-validate tokens, MILTON.ServiceDefaults implements a trusted header contract.

Keycloak Claims Transformation

At the Gateway edge, KeycloakClaimsTransformation flattens Keycloak’s deeply nested JWT payload. It extracts realm_access and resource_access arrays, mapping them into flat ASP.NET Core Role and custom permission claims.

Internal Header Authentication

Once transformed, the gateway injects the identity into HTTP headers (X-Internal-User-Id, X-Internal-Tenant-Id, etc.) and attaches a cryptographic shared secret (X-Internal-Auth). Downstream services (like the API) use the InternalHeaderAuthenticationHandler to read these headers and reconstruct the ClaimsPrincipal statelessly.

sequenceDiagram
    participant Client
    participant Gateway as YARP Gateway (BFF)
    participant Keycloak as Keycloak (OIDC)
    participant Downstream as MILTON.API

    Client->>Gateway: HTTP Request (Cookie / Bearer)
    Gateway->>Keycloak: Validate Token
    Gateway->>Gateway: KeycloakClaimsTransformation (Flatten Roles)
    Gateway->>Gateway: Strip inbound X-Internal-* headers
    Gateway->>Gateway: Inject X-Internal-* headers + Secret
    Gateway->>Downstream: Proxied Request
    Downstream->>Downstream: InternalHeaderAuthenticationHandler
    Note right of Downstream: Validates Secret, reconstructs ClaimsPrincipal
    Downstream-->>Gateway: 200 OK
    Gateway-->>Client: 200 OK

By embedding this logic in MILTON.ServiceDefaults, any new microservice added to the MILTON ecosystem automatically inherits secure, tenant-aware identity resolution.

0 items under this folder.