.NET remaps "sub" to a long URI claim type by default, causing
User.FindFirst("sub") to return null. MapInboundClaims=false
preserves the original claim names.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
72 lines
2.3 KiB
C#
72 lines
2.3 KiB
C#
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<AppDbContext>(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<TheMealDbClient>();
|
|
builder.Services.AddScoped<RecipeService>();
|
|
builder.Services.AddScoped<MealPlanService>();
|
|
builder.Services.AddScoped<ShoppingListService>();
|
|
|
|
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<AppDbContext>();
|
|
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();
|