using Microsoft.EntityFrameworkCore; using MealPlanner.Data; using MealPlanner.Services; var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers() .AddJsonOptions(o => { o.JsonSerializerOptions.ReferenceHandler = System.Text.Json.Serialization.ReferenceHandler.IgnoreCycles; o.JsonSerializerOptions.Converters.Add(new System.Text.Json.Serialization.JsonStringEnumConverter()); }); builder.Services.AddDbContext(options => options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection"))); // Zitadel JWT Bearer Auth builder.Services.AddAuthentication("Bearer") .AddJwtBearer("Bearer", options => { options.Authority = builder.Configuration["Zitadel:Issuer"] ?? "https://auth.kuns.dev"; options.Audience = builder.Configuration["Zitadel:ClientId"] ?? ""; options.MapInboundClaims = false; // Prevent .NET from remapping "sub" to long URI options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters { ValidateIssuer = true, ValidateAudience = false, // Zitadel uses client_id as audience in some configs ValidateLifetime = true, NameClaimType = "sub", }; }); builder.Services.AddAuthorization(); builder.Services.AddHttpClient(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); var allowedOrigin = builder.Configuration["AllowedOrigin"] ?? "https://essen.kuns.dev"; builder.Services.AddCors(options => options.AddDefaultPolicy(policy => policy.WithOrigins(allowedOrigin, "http://localhost:5173") .AllowAnyMethod() .AllowAnyHeader() .AllowCredentials())); builder.Services.AddHealthChecks(); var app = builder.Build(); using (var scope = app.Services.CreateScope()) { var db = scope.ServiceProvider.GetRequiredService(); db.Database.Migrate(); } app.UseCors(); if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.MapHealthChecks("/health"); app.UseStaticFiles(); app.Run();