Search code examples
c#asp.net-coremvc-mini-profilerminiprofiler

MiniProfiler ASP.NET Core - ShouldProfile based on user role


I have MiniProfiler set up in an ASP.NET Core application. Profiling works fine.

However, I only want Admins to be able to profile.

I have the following in ConfigureServices:

services.AddMiniProfiler(options =>
{
    options.ShouldProfile = request =>
        request.HttpContext.User.IsInRole("Admin");
});

The problem is, the user identity does not seem to be loaded in that method.
The User.Identity.Name property is null, and there are no claims.
My guess is that this call happens before that info is populated?

How can I profile based on the user identity?


Solution

  • You need to know that according to the docs the ClaimsPrincipal.IsInRole() method checks for Claims of type ClaimsIdentity.RoleClaimType.Be sure you have added the role claims.

    Here is a working demo you could follow:

    1.Register the user with name a@qq.com successfully.

    2.Generate the role and add the role with claims to the user:

    public async Task CreateRolesandUsers()
    {
        bool x = await _roleManager.RoleExistsAsync("Admin");
        if (!x)
        {
            // first we create Admin role   
            var role = new IdentityRole();
            role.Name = "Admin";
            await _roleManager.CreateAsync(role);
             
             //must add the claim,otherwise IsInRole would always be false..
            _roleManager.AddClaimAsync(role, new Claim(ClaimTypes.AuthorizationDecision, "Admin")).Wait();
        }
        var user = _userManager.FindByNameAsync(User.Identity.Name).Result;
        if (user != null)
        {
            var result1 = await _userManager.AddToRoleAsync(user, "Admin");
        }
    }
    

    2.Startup.cs:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(
                Configuration.GetConnectionString("DefaultConnection")));
    
        services.AddIdentity<IdentityUser, IdentityRole>()
                .AddEntityFrameworkStores<ApplicationDbContext>().AddDefaultUI();
    
        services.AddMiniProfiler(options =>
        {
            options.RouteBasePath = "/profiler";
            options.ShouldProfile = request =>
    request.HttpContext.User.IsInRole("Admin");
            options.SqlFormatter = new StackExchange.Profiling.SqlFormatters.InlineFormatter();
        });
        services.AddControllersWithViews();
        services.AddRazorPages();
    }
    
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseHttpsRedirection();
        app.UseStaticFiles();
    
        app.UseRouting();
    
        app.UseAuthentication();  //be sure add this
        app.UseAuthorization();  
    
        app.UseMiniProfiler();     //add this before UseEndpoints
    
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
            endpoints.MapRazorPages();
        });
    }
    

    Result:

    enter image description here