using Bff.Api; using Microsoft.AspNetCore.Authentication.JwtBearer; var builder = WebApplication.CreateBuilder(args); var keycloakAuthority = builder.Configuration["Keycloak:Authority"] ?? throw new InvalidOperationException("Missing configuration 'Keycloak:Authority'"); var domainBaseUrl = builder.Configuration["Downstream:Domain:BaseUrl"] ?? throw new InvalidOperationException("Missing configuration 'Downstream:Domain:BaseUrl'"); var projectionBaseUrl = builder.Configuration["Downstream:Projection:BaseUrl"] ?? throw new InvalidOperationException("Missing configuration 'Downstream:Projection:BaseUrl'"); // Validate Keycloak-issued tokens (ADR-0010). Audience validation is off for the walking skeleton — // Keycloak's audience mapping is a later hardening; signature/issuer/expiry are validated. builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.Authority = keycloakAuthority; options.RequireHttpsMetadata = false; options.TokenValidationParameters.ValidateAudience = false; }); builder.Services.AddAuthorization(); // The BFF is the portals' only backend; it fans out to the domain and projection (§8.3). builder.Services.AddHttpClient(c => c.BaseAddress = new Uri(domainBaseUrl)); builder.Services.AddHttpClient(c => c.BaseAddress = new Uri(projectionBaseUrl)); builder.Services.AddHealthChecks(); builder.Services.AddOpenApi(); var app = builder.Build(); app.UseAuthentication(); app.UseAuthorization(); app.MapHealthChecks("/health"); app.MapOpenApi(); // STUB (red): no auth requirement, no downstream call, no filtering. app.MapPost("/self-service/registrations", () => Results.Ok()); app.MapGet("/openbaar/register", (string? q) => Results.Ok(Array.Empty())); app.Run(); // Exposed so the test host (WebApplicationFactory) can boot the app. public partial class Program;