using BlazorComponentBus; using Microsoft.AspNetCore.Components.Authorization; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using MudBlazor.Services; using NLog.Web; using Quartz; using RobotNet.IdentityServer.Components; using RobotNet.IdentityServer.Components.Account; using RobotNet.IdentityServer.Components.Layout; using RobotNet.IdentityServer.Data; using RobotNet.IdentityServer.Services; using System.Security.Cryptography.X509Certificates; using static OpenIddict.Abstractions.OpenIddictConstants; var builder = WebApplication.CreateBuilder(args); builder.Host.UseNLog(); // builder.AddServiceDefaults(); builder.Services.AddControllers(); builder.Services.AddControllersWithViews(); builder.Services.AddMudServices(); // Add services to the container. builder.Services.AddRazorComponents() .AddInteractiveServerComponents(); builder.Services.AddScoped(); builder.Services.AddCascadingAuthenticationState(); builder.Services.AddScoped(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found."); builder.Services.AddDbContext(options => { options.UseSqlServer(connectionString); options.UseOpenIddict(); }); builder.Services.AddDatabaseDeveloperPageExceptionFilter(); builder.Services.AddIdentity(options => { options.SignIn.RequireConfirmedAccount = true; options.Lockout.AllowedForNewUsers = false; options.Password.RequireNonAlphanumeric = false; options.Password.RequireUppercase = false; options.Password.RequireLowercase = false; options.Password.RequireDigit = false; }) .AddEntityFrameworkStores() .AddDefaultTokenProviders(); builder.Services.AddSingleton, IdentityNoOpEmailSender>(); builder.Services.AddQuartz(options => { options.UseSimpleTypeLoader(); options.UseInMemoryStore(); }); builder.Services.AddQuartzHostedService(options => options.WaitForJobsToComplete = true); builder.Services.AddOpenIddict() .AddCore(options => { // Configure OpenIddict to use the Entity Framework Core stores and models. // Note: call ReplaceDefaultEntities() to replace the default OpenIddict entities. options.UseEntityFrameworkCore() .UseDbContext(); // Enable Quartz.NET integration. options.UseQuartz(); }) .AddServer(options => { options.SetIssuer(builder.Configuration["OpenIddictCertificate:Issuer"] ?? throw new InvalidOperationException("OpenIddictCertificate Issuer is not configured.")); // Enable the authorization, logout, token and userinfo endpoints. options.SetAuthorizationEndpointUris("api/Authorization/connect/authorize") .SetEndSessionEndpointUris("api/Authorization/connect/logout") .SetIntrospectionEndpointUris("connect/introspect") .SetTokenEndpointUris("api/Authorization/connect/token") .AllowClientCredentialsFlow() .SetUserInfoEndpointUris("api/Userinfo") .SetEndUserVerificationEndpointUris("connect/verify"); // Mark the "email", "profile" and "roles" scopes as supported scopes. options.RegisterScopes(Scopes.Email, Scopes.Profile, Scopes.Roles); // Note: this sample only uses the authorization code and refresh token // flows but you can enable the other flows if you need to support // implicit, password or client credentials. options.AllowAuthorizationCodeFlow() .AllowRefreshTokenFlow() .AllowClientCredentialsFlow(); if (builder.Environment.IsDevelopment()) { // Register the signing and encryption credentials. options.AddDevelopmentEncryptionCertificate() .AddDevelopmentSigningCertificate(); // Thêm ephemeral encryption key //options.AddEphemeralEncryptionKey() // .AddEphemeralSigningKey(); // Thêm signing key tạm thời } else if (builder.Environment.IsProduction()) { // Thêm ephemeral encryption key // Sử dụng chứng chỉ thực tế var path = builder.Configuration["OpenIddictCertificate:Path"] ?? throw new InvalidOperationException("Certificate path is not configured."); var password = builder.Configuration["OpenIddictCertificate:Password"] ?? throw new InvalidOperationException("Certificate password is not configured."); if (string.IsNullOrEmpty(path) || string.IsNullOrEmpty(password)) { throw new InvalidOperationException("Certificate path or password is not configured."); } var certificate = X509CertificateLoader.LoadPkcs12FromFile(path, password); options.AddEncryptionCertificate(certificate) .AddSigningCertificate(certificate); } options.UseDataProtection() .PreferDefaultAccessTokenFormat() .PreferDefaultAuthorizationCodeFormat() .PreferDefaultRefreshTokenFormat(); // Register the ASP.NET Core host and configure the ASP.NET Core-specific options. options.UseAspNetCore() .EnableAuthorizationEndpointPassthrough() .EnableEndSessionEndpointPassthrough() .EnableTokenEndpointPassthrough() .EnableUserInfoEndpointPassthrough() .EnableStatusCodePagesIntegration(); // Can thiệp vào sự kiện logging }) .AddValidation(options => { // Import the configuration from the local OpenIddict server instance. options.UseLocalServer(); // Register the ASP.NET Core host. options.UseAspNetCore(); }); builder.Services.AddCors(options => { options.AddPolicy("RequestAuthorize", policy => { policy.AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader(); }); }); builder.Services.AddMudServices(); var app = builder.Build(); await app.Services.SeedApplicationDbAsync(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseMigrationsEndPoint(); } else { app.UseExceptionHandler("/Error", createScopeForErrors: true); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseCors("RequestAuthorize"); app.MapControllers(); app.UseAuthentication(); app.UseAuthorization(); app.UseAntiforgery(); app.MapStaticAssets(); app.MapRazorComponents() .AddInteractiveServerRenderMode(); app.MapAdditionalIdentityEndpoints(); app.Run();