0
votes

I'm trying to implement role-based authorization in Asp.Net Core 2.1 according to Microsoft documentation

Here is how my Startup.cs looks like:

    public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<CookiePolicyOptions>(options =>
        {
            // This lambda determines whether user consent for non-essential cookies is needed for a given request.
            options.CheckConsentNeeded = context => true;
            options.MinimumSameSitePolicy = SameSiteMode.None;
        });

        services.Configure<IdentityOptions>(options =>
        {
            // Password settings.
            options.Password.RequireDigit = true;
            options.Password.RequireLowercase = true;
            options.Password.RequireNonAlphanumeric = false;
            options.Password.RequireUppercase = true;
            options.Password.RequiredLength = 6;
            options.Password.RequiredUniqueChars = 0;
        });

        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(
                Configuration.GetConnectionString("DefaultConnection")));

        services.AddDefaultIdentity<IdentityUser>()
            .AddRoles<IdentityRole>()                
            .AddEntityFrameworkStores<ApplicationDbContext>();

        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseCookiePolicy();
        app.UseAuthentication();

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }

And here is controller code:

    [Authorize(Roles = "Admin")]
    public IActionResult About()
    {
        ViewData["Message"] = "Your application description page.";

        return View();
    }

However, when I try to access this page via test account that has Admin role assigned - I'm getting "Access denied" error. I've checked and on DB side everything is configured properly - there is Admin role in AspNetRoles table and my user has this role in AspNetUserRoles table. I've added role and connection to user via RoleManager and UserManager respectivly previously. Also [Authorize] tag itself works also properly (doesn't allow to see page for unatenticated user). My questions is - why role based authorization doesn't work?

1
it's hard to tell what's wrong, but you can debug it, either directly into the source code or create your own custom IAuthorizationService as in an answer of mine here stackoverflow.com/a/66665391/1679602 - there you just need the HttpAppAuthorizationService and set a breakpoint after var result = to see the result, the purpose is to examine the AuthorizationResult.Failure.FailedRequirements - you will see clearly the reason for the access deny.King King
Thanks for advice. What I've figured out is that if I call HttpContext.User.IsInRole("Admin") method it will return "false". However, if I call _userManager.IsInRole(user, "Admin") it will return true and similarly _userManager.GetRolesAsync(user) returns "Admin" role. So it looks like app doesn't know that role-based authorization persists. Though still don't understand why it happens...Wadim
your user's role of Admin is persisted to the db but the authentication process somehow does not load that into the authentication ticket which is sent in the cookies. But if you use Identity, that process should just work. You can debug into the source code (the SignInAsync method) to check more about that. I doubt that your cookies is not cleared after the last signing-in, and that cookies contains the old authentication ticket which does not contain the Admin role. If possible, try clearing the cookies on the browser and retry if it fixes the issue.King King

1 Answers

0
votes

Issue was resolved by upgrading to Asp.Net Core 3.1