using System.Text; using API; using Domain; using Infrastructure; using Infrastructure.Services.Authentication; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.IdentityModel.Tokens; using Microsoft.OpenApi.Models; var builder = WebApplication.CreateBuilder(args); StartupHelper.EnsureKeysGenerated(builder.Configuration, builder.Environment.ContentRootPath); StartupHelper.EnsureMongoDatabaseAndCollectionsExist(builder.Configuration); StartupHelper.EnsurePythonEnvironment(builder.Environment.ContentRootPath); builder.WebHost.ConfigureKestrel((context, serverOptions) => { serverOptions.Configure(context.Configuration.GetSection("Kestrel"), true); }); builder.Services.AddCors(options => { options.AddPolicy("AllowAll", corsPolicyBuilder => { corsPolicyBuilder.AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader() .WithExposedHeaders("*"); // This exposes all headers }); }); builder.Services.AddControllers(); builder.Services.AddInfrastructureServices(builder.Configuration); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(c => { // Add Bearer token authentication c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme { Description = "JWT Authorization header using the Bearer scheme. Example: 'Authorization: Bearer {token}'", Name = "Authorization", In = ParameterLocation.Header, Type = SecuritySchemeType.Http, Scheme = "Bearer" }); c.AddSecurityRequirement(new OpenApiSecurityRequirement { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" }, Scheme = "oauth2", Name = "Bearer", In = ParameterLocation.Header }, new List() } }); // Add API key authentication c.AddSecurityDefinition("ApiKey", new OpenApiSecurityScheme { Description = "API key needed to access the endpoints. ApiKey must appear in header", Type = SecuritySchemeType.ApiKey, Name = "ApiKey", In = ParameterLocation.Header }); // Apply the security to all Swagger documents c.AddSecurityRequirement(new OpenApiSecurityRequirement() { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" }, Scheme = "oauth2", Name = "Bearer", In = ParameterLocation.Header }, new List() }, { new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "ApiKey" }, In = ParameterLocation.Header }, new List() } }); }); builder.Services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(options => { options.Events = new JwtBearerEvents { OnAuthenticationFailed = context => { Console.WriteLine("Authentication failed: " + context.Exception.Message); return Task.CompletedTask; }, OnTokenValidated = context => { Console.WriteLine("Token validated: " + context.SecurityToken); return Task.CompletedTask; }, OnChallenge = context => { Console.WriteLine("OnChallenge error: " + context.ErrorDescription); return Task.CompletedTask; } }; options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(builder.Configuration["Jwt:SecretKey"])), ValidateIssuer = true, ValidateAudience = true, ValidIssuer = builder.Configuration["Jwt:Issuer"], ValidAudience = builder.Configuration["Jwt:Audience"], ClockSkew = TimeSpan.Zero }; }) .AddScheme("ApiKey", options => { }); builder.Services.AddAuthorizationBuilder() .AddPolicy(Policies.AdminPolicy, policy => { policy.RequireRole(UserRoles.Admin); }) .AddPolicy(Policies.DoctorPolicy, policy => { policy.RequireRole(UserRoles.Admin, UserRoles.Doctor); }) .AddPolicy(Policies.PatientPolicy, policy => { policy.RequireRole(UserRoles.Patient, UserRoles.Admin); }) .AddPolicy(Policies.AuthenticatedPolicy, policy => { policy.RequireRole(UserRoles.Patient, UserRoles.Admin, UserRoles.Doctor); }) .AddPolicy(Policies.ClientsOnlyPolicy, policy => { policy.RequireRole(UserRoles.Patient, UserRoles.Doctor); }) .AddPolicy(Policies.AnonymousPolicy, policy => { policy.RequireAssertion(_ => true); }); var app = builder.Build(); if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseCors("AllowAll"); app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); using (var scope = app.Services.CreateScope()) { var services = scope.ServiceProvider; var dbContext = services.GetRequiredService(); // Directly resolving your DbContext StartupHelper.EnsureDatabaseCreated(dbContext); } app.Run();