Changed Auth to use Identity, with easy to set passsword requirenments via appsettings.json

This commit is contained in:
Matěj Kubíček
2026-05-01 18:07:27 +02:00
parent 3581fce0df
commit ea11e6969b
25 changed files with 1107 additions and 561 deletions
+31 -22
View File
@@ -1,9 +1,8 @@
using dotenv.net;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using TemplateWeb.Data;
using TemplateWeb.Interfaces;
using TemplateWeb.Services;
using TemplateWeb.Entities;
namespace TemplateWeb;
@@ -15,29 +14,38 @@ public class Program
var builder = WebApplication.CreateBuilder(args);
// gets the connection string from configuration
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection")
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection")
?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseNpgsql(connectionString));
builder.Services.AddControllersWithViews();
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
// Configure Identity — password requirements are read from appsettings.json "Identity:Password"
var pwSection = builder.Configuration.GetSection("Identity:Password");
builder.Services.AddIdentity<UserEntity, IdentityRole>(options =>
{
options.LoginPath = "/Auth/Login";
options.AccessDeniedPath = "/Auth/AccessDenied";
options.ExpireTimeSpan = TimeSpan.FromHours(2);
});
builder.Services.AddAuthorization();
builder.Services.AddScoped<IAuthService, AuthService>();
builder.Services.AddHttpContextAccessor();
options.Password.RequiredLength = pwSection.GetValue<int>("RequiredLength", 6);
options.Password.RequireDigit = pwSection.GetValue<bool>("RequireDigit", true);
options.Password.RequireLowercase = pwSection.GetValue<bool>("RequireLowercase", true);
options.Password.RequireUppercase = pwSection.GetValue<bool>("RequireUppercase", true);
options.Password.RequireNonAlphanumeric = pwSection.GetValue<bool>("RequireNonAlphanumeric", false);
options.Password.RequiredUniqueChars = pwSection.GetValue<int>("RequiredUniqueChars", 1);
})
.AddEntityFrameworkStores<AppDbContext>()
.AddDefaultTokenProviders();
builder.Services.ConfigureApplicationCookie(options =>
{
options.LoginPath = "/Auth/Login";
options.AccessDeniedPath = "/Auth/AccessDenied";
options.ExpireTimeSpan = TimeSpan.FromHours(2);
});
var app = builder.Build();
// Apply migrations on startup
// Apply migrations and seed on startup
using (var scope = app.Services.CreateScope())
{
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
@@ -45,9 +53,10 @@ public class Program
{
db.Database.Migrate();
}
// Seed the initial admin user
DataSeeder.SeedAdminUser(db).GetAwaiter().GetResult();
var userManager = scope.ServiceProvider.GetRequiredService<UserManager<UserEntity>>();
var roleManager = scope.ServiceProvider.GetRequiredService<RoleManager<IdentityRole>>();
DataSeeder.SeedAsync(userManager, roleManager).GetAwaiter().GetResult();
}
// Configure the HTTP request pipeline.
@@ -65,7 +74,7 @@ public class Program
app.MapControllerRoute(
name: "areas",
pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}")
@@ -73,4 +82,4 @@ public class Program
app.Run();
}
}
}