I am developing a .NET 7 Web application that has secured areas.
This is a monolith application, so that it is separated in different assemblies. I have one host assembly (the entry assembly), called EntryPortal.Core
. On the other hand, I have other assembly called Modules.Authenticate.Core
.
The entry portal assembly has this code to load the authentication assembly:
builder.Services.AddModule<Modules.Authenticate.Core.Startup>("Authenticate", builder.Configuration);
var app = builder.Build();
app.UseRouting();
app.UseAuthorization();
app.MapControllers();
app.MapDefaultControllerRoute();
var modules = app.Services.GetRequiredService<IEnumerable<Module>>();
foreach (var module in modules)
{
app.Map($"/{module.RoutePrefix}", ab =>
{
ab.UseRouting();
module.Startup.Configure(ab);
});
}
That way, I call the Startup class of every module.
So far, the assemblies separation works well, but now I am implementing secured pages.
This is the Startup class of the module:
public class Startup : IModuleStartup
{
public void ConfigureServices(IServiceCollection services, IConfiguration configuration)
{
services.AddTransient<IPasswordHasher<ApplicationUser>, CustomPasswordHasher>();
services.AddTransient<IEmailSender, EmailSender>();
services.AddIdentity<ApplicationUser, ApplicationRole>(options =>
{
options.SignIn.RequireConfirmedEmail = true;
options.Stores.MaxLengthForKeys = 128;
options.User.RequireUniqueEmail = true;
})
.AddDefaultTokenProviders();
services.AddTransient<IUserStore<ApplicationUser>, CustomUserStore>();
services.AddTransient<IRoleStore<ApplicationRole>, CustomRoleStore>();
services.AddScoped<IAccountService, AccountService>();
services.AddScoped<IUsuarioService, UsuarioService>();
services.AddDbContext<SecuWebModulesAuthenticateContext>(options =>
{
options
.UseSqlServer(configuration.GetConnectionString("Modules.Authenticate"));
#if DEBUG
options.LogTo(x => Debug.WriteLine(x));
#endif
});
// Agrega autenticación
services.AddAuthentication()
.AddCookie("Cookies", options =>
{
options.LoginPath = "/Security/Login";
options.LogoutPath = "/Security/Logout";
options.AccessDeniedPath = "/Security/AccessDenied";
options.ReturnUrlParameter = "ReturnUrl";
})
.AddJwtBearer(x =>
{
x.RequireHttpsMetadata = true;
x.SaveToken = true;
x.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = configuration["Modules:Authenticate:AuthJwt:Issuer"],
ValidateAudience = true,
ValidAudience = configuration["Modules:Authenticate:AuthJwt:Audience"],
ValidateIssuerSigningKey = true,
RequireExpirationTime = false,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["Modules:Authenticate:AuthJwt:Key"] ?? string.Empty))
};
});
services.AddAuthorization();
}
public void Configure(IApplicationBuilder app)
{
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
On the other hand, I have this controller:
[Authorize]
public class UsuarioController : Controller
{
public IActionResult Index()
{
return View();
}
}
Well, when I browse to https://localhost:7255/Usuario, this page is shown:
How can I solve this so that a redirect to the login page occurs? As you see, I have a options.LoginPath = "/Security/Login"
definition.
Thanks
Jaime