197 lines
7.3 KiB
C#
197 lines
7.3 KiB
C#
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<ComponentBus>();
|
|
builder.Services.AddCascadingAuthenticationState();
|
|
builder.Services.AddScoped<NavMenu>();
|
|
builder.Services.AddSingleton<PasswordStrengthService>();
|
|
builder.Services.AddSingleton<UserInfoService>();
|
|
builder.Services.AddScoped<UserImageService>();
|
|
builder.Services.AddScoped<IdentityService>();
|
|
builder.Services.AddScoped<IdentityUserAccessor>();
|
|
builder.Services.AddScoped<IdentityRedirectManager>();
|
|
builder.Services.AddScoped<AuthenticationStateProvider, IdentityRevalidatingAuthenticationStateProvider>();
|
|
|
|
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");
|
|
builder.Services.AddDbContext<ApplicationDbContext>(options =>
|
|
{
|
|
options.UseSqlServer(connectionString);
|
|
options.UseOpenIddict();
|
|
});
|
|
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
|
|
|
|
builder.Services.AddIdentity<ApplicationUser, ApplicationRole>(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<ApplicationDbContext>()
|
|
.AddDefaultTokenProviders();
|
|
|
|
builder.Services.AddSingleton<IEmailSender<ApplicationUser>, 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<ApplicationDbContext>();
|
|
|
|
// 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<App>()
|
|
.AddInteractiveServerRenderMode();
|
|
|
|
app.MapAdditionalIdentityEndpoints();
|
|
|
|
app.Run();
|