skip to Main Content

I’m trying to create the initial page that comes up as soon as the program runs in an ASP.NET Core 7 MVC project. I want this initial page to be the login screen from Identity. I will customize this login screen using an external template I found. In the template I’ve applied, I want the login button to redirect to different pages based on the role of the person logging in. There are two roles in the project, and I want each of them to be directed to their respective pages when they log in. How can I achieve this?

Here is my program.cs:

global using Infrastructure.Identity;
global using Infrastructure.Data;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Localization;
using System.Globalization;
using Microsoft.Extensions.Options;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Mvc.Razor;

namespace Web
{
    public class Program
    {
        public static async Task Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);

            // Add services to the container.
            var connectionStringIdentity = builder.Configuration.GetConnectionString("TalentFlowIdentityDb") ?? throw new InvalidOperationException("Connection string 'TalentFlowIdentityDb' not found.");
            builder.Services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(connectionStringIdentity));
            var connectionStringMain = builder.Configuration.GetConnectionString("TalentFlowDb") ?? throw new InvalidOperationException("Connection string 'TalentFlowDb' not found.");
            builder.Services.AddDbContext<TalentFlowDbContext>(options =>
                options.UseSqlServer(connectionStringMain));
            builder.Services.AddDatabaseDeveloperPageExceptionFilter();

            builder.Services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = false)
                .AddRoles<IdentityRole>()
                .AddEntityFrameworkStores<ApplicationDbContext>();

            builder.Services.AddControllersWithViews();

            builder.Services.AddRazorPages();

            builder.Services.ConfigureApplicationCookie(options =>
            {                
                options.LoginPath = $"/Identity/Account/Login";
                options.LogoutPath = $"/Identity/Account/Logout";
            });

            builder.Services.AddMvc().AddRazorPagesOptions(options => options.Conventions.AddAreaPageRoute("Identity", "/Account/Login", ""));


            var app = builder.Build();

            // Configure the HTTP request pipeline.
            if (app.Environment.IsDevelopment())
            {
                app.UseMigrationsEndPoint();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                // 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.UseRouting();

            app.UseAuthentication();
            app.UseAuthorization();

            app.MapRazorPages();
            app.MapControllerRoute(
                name: "areas",
                pattern: "{area:exists}/{controller=Account}/{action=Login}/{id?}");

            //app.MapControllerRoute(
            //    name: "default",
            //    pattern: "{controller=Home}/{action=LoginPage}/{id?}");


            using (var scope = app.Services.CreateScope())
            {
                var appIdentityDb = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
                var roleManager = scope.ServiceProvider.GetRequiredService<RoleManager<IdentityRole>>();
                var userManager = scope.ServiceProvider.GetRequiredService<UserManager<ApplicationUser>>();
                await ApplicationDbContextSeed.SeedAsync(appIdentityDb, roleManager, userManager);
            }


            app.Run();
        }
    }
}

3

Answers


  1. Chosen as BEST ANSWER

    Thanks for the reply onupicakci. But your code did not solve my problem but of course it showerd me a way to do it. I changed OnPost method as per below and now I don't have any problem:

    public async Task<IActionResult> OnPostAsync(string returnUrl = null)
    {
       returnUrl ??= Url.Content("~/");
    
       ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
    
      if (ModelState.IsValid)
      {
        // This doesn't count login failures towards account lockout
        // To enable password failures to trigger account lockout, set lockoutOnFailure: true
        var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: false);
        if (result.Succeeded)
        {
            IList<string> roles = new List<string>();
            //var userName = HttpContext.User.Identity.Name;
            var _userid = await _userManager.FindByNameAsync(Input.Email);
            if (_userid != null)
            {
                var id = _userid.Id;
                await _userManager.UpdateSecurityStampAsync(_userid);
                await _signInManager.RefreshSignInAsync(_userid);
                roles = await _userManager.GetRolesAsync(_userid);
            }
            //var user = _userManager.FindByNameAsync(userName).Result;
    
            _logger.LogInformation("User logged in.");
            if (roles[0] == "CompanyManager")
            {
                return LocalRedirect(returnUrl);
    
            }
            else if (roles[0] == ("Personnel"))
            {
                var localUrl = Url.Action("Index", "PersonnelMainPage", new { area = "Personnel" });
                return LocalRedirect(localUrl);
    
            }
    
    
    
    
        }
        if (result.RequiresTwoFactor)
        {
            return RedirectToPage("./LoginWith2fa", new { ReturnUrl = returnUrl, RememberMe = Input.RememberMe });
        }
        if (result.IsLockedOut)
        {
            _logger.LogWarning("User account locked out.");
            return RedirectToPage("./Lockout");
        }
        else
        {
            ModelState.AddModelError(string.Empty, "Invalid login attempt.");
            return Page();
        }
    }
    
    // If we got this far, something failed, redisplay form
    return Page();
    

    }


  2. Open Login.cshtml.cs in Areas/Identity/Pages/Account

    public async Task<IActionResult> OnPostAsync(string returnUrl = null)
    {
        if (result.Succeeded)
        {
            var user = await _userManager.FindByNameAsync(Input.Email);
            var roles = await _userManager.GetRolesAsync(user);
    
            if (roles.Contains("Role1"))
            {
                return RedirectToPage("/Path/To/Role1Page");
            }
            else if (roles.Contains("Role2"))
            {
                return RedirectToPage("/Path/To/Role2Page");
            }
            else
            {
                return LocalRedirect(returnUrl);
            }
        }
    }
    

    You can apply it this way.

    Login or Signup to reply.
  3. My advice here is to move the logic of roles out of the view layer and work with the native AuthenticationHandler:
    AuthenticationHandler’s doc

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search