Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *

53 Comments

  1. internal class PermissionPolicyProvider : IAuthorizationPolicyProvider
    {
    public DefaultAuthorizationPolicyProvider FallbackPolicyProvider { get; }
    public PermissionPolicyProvider(IOptions options)
    {
    FallbackPolicyProvider = new DefaultAuthorizationPolicyProvider(options);
    }
    public Task GetDefaultPolicyAsync() => FallbackPolicyProvider.GetDefaultPolicyAsync();
    public Task GetPolicyAsync(string policyName)
    {
    if (policyName.StartsWith(“Permission”, StringComparison.OrdinalIgnoreCase))
    {
    var policy = new AuthorizationPolicyBuilder();
    policy.AddRequirements(new PermissionRequirement(policyName));
    return Task.FromResult(policy.Build());
    }
    return FallbackPolicyProvider.GetPolicyAsync(policyName);
    }
    public Task GetFallbackPolicyAsync() => FallbackPolicyProvider.GetDefaultPolicyAsync();
    }

    I dont get this code. where did u get this code from?

  2. If I am writing on blazor. How can I achhevie this word

    @using Microsoft.AspNetCore.Authorization
    @inject IAuthorizationService AuthorizationService
    @using PermissionManagement.MVC.Constants
    Product Management

    @if ((AuthorizationService.AuthorizeAsync(User, Permissions.Products.Create)).Result.Succeeded)
    {
    Create
    }
    @if ((AuthorizationService.AuthorizeAsync(User, Permissions.Products.View)).Result.Succeeded)
    {
    View
    }
    @if ((AuthorizationService.AuthorizeAsync(User, Permissions.Products.Edit)).Result.Succeeded)
    {
    Modify
    }
    @if ((AuthorizationService.AuthorizeAsync(User, Permissions.Products.Delete)).Result.Succeeded)
    {
    Delete
    }

    It seemed there is erorr showing User is datatype use as variable.

    1. Hi there
      Did you manage this solution with Blazor.
      If so could you please show us how to.
      Thank you very much for your cooperation.

  3. I’m trying to convert this to Razor pages and for the most part, I’m successful. A few things to note when developing this from scratch.
    1) Make sure you add .AddRoles() after your services.AddDefaultIdentity()
    2) If doing this by hand (not copy and paste) don’t forget to put host.Run() or await host.RunAsync() at the end of your Main code (doh!)

    Thanks for the work!

  4. Hello Mukesh,
    I am a beginner in this domain and found out your admin lte starter kit with .net core 3.1. Now I don’t u understand many things.
    1) How to I add custom views using controllers as there is no default controller folder. Do I have to create one? If yes then where.

    2) When I install the extension a default db starting with “aspnet” and then some long gibberish is created. I tried adding a table to it and then on using the scaffold command to generate models it generates models for all the tables including the identity ones. Now, how do I use this table to perform CRUD with MVC.

    3) Correct me if I’m wrong. I thought this was a .net core project with razor pages but upon reading your quick start it seems that its MVC. So, where do I create the controllere folder?

    4) And, if I want to use that template with razor pages what will I have to do ? Please guide.

    I really need your help or anyone else who can answer my questions. Really appreciate any kind of help. Thank you!

  5. hi mukesh
    After completing all the steps and making a run for the project, the main page of the site is not displayed until after logging in?

  6. Thank You, Very good explanation.
    I have a question:
    If I have more than one stock management system with the same users, How can I handle users’ permission?
    For example:
    User A has to write permission on stock management 1
    User A has just view permission on stock management 2

  7. thanks for your nice article, I wish to apply it to my own project but through the controller/action, not a permission class because I have more than 100 actions and models! do u have any suggestion for me?

  8. Is it possible to create a random role and then select if they can for example CRUD production, and just read another, etc? How is this done when you have to “hard code” the role in the authorize attribute on the controller?

  9. Hi Mukesh
    After completing all the steps and making a run for the project, how to check by skipping the login step when running the project for the first time ?
    please help me

  10. I dont use EntityFramework, ASP identity tables however above projects looks cool, so can we achieve similar with other Dapper with Custom identity tables ? I am trying to find out when exactly it is attaching Role Claim but didn’t got it working…Any input?

    1. I am using Code First Approach – EFCore. You don’t need a DB file to make this implementation running. Just use the EF Tool commands to generate the database.
      Regards

  11. What happen when try to consult a Permission that don´t start whith Permission.model.action prefix what return to the view?

  12. Hi Mukesh, Thanks for this clear demo.
    in a normal project, we have more than one entity. you explain in this example using product entity. what should I do to apply this concept on more than one entity? should I repeat this code snippet for every entity?
    public static List GeneratePermissionsForModule(string module)
    {
    return new List()
    {
    $”Permissions.{module}.Create”,
    $”Permissions.{module}.View”,
    $”Permissions.{module}.Edit”,
    $”Permissions.{module}.Delete”,
    };
    }
    public static class Products
    {
    public const string View = “Permissions.Products.View”;
    public const string Create = “Permissions.Products.Create”;
    public const string Edit = “Permissions.Products.Edit”;
    public const string Delete = “Permissions.Products.Delete”;
    }

    1. Update GetPermissions method that it loops through each Property

      public static void GetPermissions(this List allPermissions, string roleId)
      {
      var fields = new List();

      foreach (var p in typeof(Constants.Permissions).GetNestedTypes())
      {
      fields.AddRange(p.GetFields(BindingFlags.Static | BindingFlags.Public).ToList());
      }

      foreach (FieldInfo fi in fields)
      {
      allPermissions.Add(new RoleClaimsViewModel { Value = fi.GetValue(null).ToString(), Type = “Permissions” });
      }
      }

  13. Hi Mukesh, Thanks for you.
    in a normal project, we have more than one entity. you explain in this example using product entity. what should I do to apply this concept on more than one entity?

  14. Hi Mukesh. Thanks for sharing your knowledge.

    I am having an error in the UserRolesController:
    An unhandled exception occurred while processing the request.
    InvalidOperationException: There is already an open DataReader
    associated with this Connection which must be closed first.

    i’ve checked all , and didnt’n find a solution. Here is the code of this block:
    public async Task Index(string userId)
    {
    var viewModel = new List();
    var user = await _userManager.FindByIdAsync(userId);
    foreach (var role in _roleManager.Roles)
    {
    var userRolesViewModel = new UserRolesViewModel
    {
    RoleName = role.Name
    };
    if (await _userManager.IsInRoleAsync(user, role.Name))
    {
    userRolesViewModel.Selected = true;
    }
    else
    {
    userRolesViewModel.Selected = false;
    }

    viewModel.Add(userRolesViewModel);
    }
    var model = new ManageUserRolesViewModel()
    {
    UserId = userId,
    UserRoles = viewModel
    };

    return View(model);
    }
    ……..thanks any help.

    1. Hi,
      in the code block you sent, can you change foreach (var role in _roleManager.Roles) to foreach (var role in _roleManager.Roles.ToList())

      That should probably fix the issue you have. Do let me know! Thanks

  15. Hi
    My site has large number of permission , say 100 modules and each modules has View, Create,Edit,Delete permission.
    So total claim will be 400. i.e 400 rows in [AspNetRoleClaims]

    When I have large permissions, Cookie length exceed to max supported size by the browser. In this case, it will throw.HTTP Error 400. The size of the request headers is too long.
    Is there any way we can fix this issue when using claim based authorization?
    When a role has about 200+ claim permission, such user get those error (“Cookie length exceed …”)

  16. Great Tutorial.

    After following it within my project, I have an issue where it looks like there is a recursion when the code redirects to login; the requested url ends up being (below).

    If I comment out the policy startup, I receive the login page and it works fine – once logged in, everything is good (even if I add the policy startup back in) until the user is logged out. I’ve set breakpoints, I don’t see where any of the policy code is called during this – so I am at somewhat of a loss as to how to troubleshoot this? Any ideas?

    — Below is the generated login url, you can see the information repeated over and over again inside the url. —

    https://localhost:44391/Account/Login?ReturnUrl=%2FAccount%2FLogin%3FReturnUrl%3D%252FAccount%252FLogin%253FReturnUrl%253D%25252FAccount%25252FLogin%25253FReturnUrl%25253D%2525252FAccount%2525252FLogin%2525253FReturnUrl%2525253D%252525252FAccount%252525252FLogin%252525253FReturnUrl%252525253D%25252525252FAccount%25252525252FLogin%25252525253FReturnUrl%25252525253D%2525252525252FAccount%2525252525252FLogin%2525252525253FReturnUrl%2525252525253D%252525252525252FAccount%252525252525252FLogin%252525252525253FReturnUrl%252525252525253D%25252525252525252FAccount%25252525252525252FLogin%25252525252525253FReturnUrl%25252525252525253D%2525252525252525252FAccount%2525252525252525252FLogin%2525252525252525253FReturnUrl%2525252525252525253D%252525252525252525252FAccount%252525252525252525252FLogin%252525252525252525253FReturnUrl%252525252525252525253D%25252525252525252525252FAccount%25252525252525252525252FLogin%25252525252525252525253FReturnUrl%25252525252525252525253D%2525252525252525252525252FAccount%2525252525252525252525252FLogin%2525252525252525252525253FReturnUrl%2525252525252525252525253D%252525252525252525252525252FAccount%252525252525252525252525252FLogin%252525252525252525252525253FReturnUrl%252525252525252525252525253D%25252525252525252525252525252FAccount%25252525252525252525252525252FLogin%25252525252525252525252525253FReturnUrl%25252525252525252525252525253D%2525252525252525252525252525252FAccount%2525252525252525252525252525252FLogin%2525252525252525252525252525253FReturnUrl%2525252525252525252525252525253D%252525252525252525252525252525252FAccount%252525252525252525252525252525252FLogin%252525252525252525252525252525253FReturnUrl%252525252525252525252525252525253D%25252525252525252525252525252525252FAccount%25252525252525252525252525252525252FLogin%25252525252525252525252525252525253FReturnUrl%25252525252525252525252525252525253D%2525252525252525252525252525252525252FAccount%2525252525252525252525252525252525252FLogin%2525252525252525252525252525252525253FReturnUrl%2525252525252525252525252525252525253D%252525252525252525252525252525252525252FAccount%252525252525252525252525252525252525252FLogin%252525252525252525252525252525252525253FReturnUrl%252525252525252525252525252525252525253D%25252525252525252525252525252525252525252F

    1. I see the code call this over and over inside PermissionPolicyProvider.

      public Task GetFallbackPolicyAsync() => FallbackPolicyProvider.GetDefaultPolicyAsync();

      The default is indicating that everything is denied for some reason.

      1. For other’s benefits, I am not 100% sure this is correct, however changing the PermissionPolicyProvider’s GetFallbackPolicyAsync method to this seems to at least helped the issue as far as not being able to log in.

        public Task GetFallbackPolicyAsync() => FallbackPolicyProvider.GetFallbackPolicyAsync(); // .GetDefaultPolicyAsync();

        I’m interested in what others think about this change.

        1. I am also not sure what the correct way to do it would be, but as you point out the way it was written in the example it denies everything by default (that is not marked as [AllowAnonymous]).
          My problem was not with Login (as I had it marked with [AllowAnonymous]), but my problem was that in order to see the error pages (404 not found etc.) via UseStatusCodePages you had to be Logged-in.

          Your solution seams to work and I hope it is the right way to do it, and hopefully someone can comment and confirm your solution is the correct one.

        2. For the search engines: IAuthorizationPolicyProvider AllowAnonymous not working when using this in Razor Pages. Since you cannot tag a handler method with AllowAnonymous you can’t use the Authorize attribute on the class and the AllowAnonymous attribute on the method.

          Changing this:
          public Task GetFallbackPolicyAsync() => FallbackPolicyProvider.GetDefaultPolicyAsync();
          to this:
          public Task GetFallbackPolicyAsync() => FallbackPolicyProvider.GetFallbackPolicyAsync();

          Fixes the issue and allows classes to be tagged with [AllowAnonymous]

  17. Hi Mukesh.
    Thanks for your guide.
    I have tried to implementation as your guide.
    I have problem at the rolecontroller the code has been upload to
    https://github.com/nguyentuananh921/Betting.git

    In the rolecontroller.cs
    I have the action:
    public async Task Index()
    {
    var roles = await _roleManager.Roles.ToListAsync();
    return View(roles);
    }

    And in the Index view I have done as you guide.

    //Start from here
    @model List
    @{
    ViewData[“Title”] = “Role Manager”;
    Layout = “~/Views/Shared/_Layout.cshtml”;
    }

    Role Manager

    Add New Role

    //—– remove to clear.

    The problem is when I click on the button the action does not rout to AddRole of the RoleController.

    Everything will work file if I add the row

    @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

    at the top of the index.cshtml.

    I Still confuse about why i have to add this row at each view when I have added it in the _ViewImports.cshtml

    Thanks for your guide and hoping to see you support.

  18. Thank you Mukesh for the amazing tutorial!

    There is a serious question, which already been asked by (@Jorge Curiel and @Dilli Shrestha) regarding the Cookie size limit which affects the number of permissions that can be added using this approach.

    Please help us with an alternative approach to accomplish the same task.

    1. Hi,

      I would suggest altering the permission checking strategy a bit. In cases where there are 50+ permissions involved, storing in the cookie would probably give you a ‘Header too long’ Bad Request status code. In this scenario, it’s better to implement a real-time permission checking mechanism rather than storing it in the cookie. Ideally, you would need to remove the permission added to the cookie and have an API endpoint that verifies the request for permissions using the current user role ID.

      Regards

  19. Hi, I’m using azure AD to Authorize user. But I want to add and manage user’s role in my database not using azure AD roles. How can I do this

  20. Hi,
    Good tutorial, im a novice with this but seem to have an issue with the below

    public async Task Update(PermissionViewModel model)
    {
    var role = await _roleManager.FindByIdAsync(model.RoleId);
    var claims = await _roleManager.GetClaimsAsync(role);
    foreach (var claim in claims)
    {
    await _roleManager.RemoveClaimAsync(role, claim);
    }
    var selectedClaims = model.RoleClaims.Where(a => a.Selected).ToList();
    foreach (var claim in selectedClaims)
    {
    await _roleManager.AddPermissionClaim(role, claim.Value);
    }
    return RedirectToAction(“Index”, new { roleId = model.RoleId });
    }

    speciffically this line
    await _roleManager.AddPermissionClaim(role, claim.Value);
    throws a CS0121 error.

    I have used a newer dot net. visual studio 2022

    do you know of a quick fix, or would i be better redoing this in the same dotnet. ?

    thanks
    Paul

  21. Hey there,

    First, great article! I followed your example code to write my own app. Get everything going but whatever default user I tried login failed with “Invalid Login”; the user data was never written to the db by the seeding methods. I failed to find this for several hours until I realized, I changed the default passwords to lowercase in my code – user manager CreateAsync fails if you don’t add an upper case character to the password, (by default).

    Thanks for your hard work!

  22. Hi, How can I implement the Authorization Handler method in my code, I am trying to use it in an Api project. So I am confused as to where to call it in order to proceed.
    Regards.

  23. Hi Mukesh, thanks a lot for this tutorial, it was very usefull for me.
    I only have one question:
    I am in two differents browser, one with superAdmin role and other with basic role.
    If I change permissions using superAdmin role, I need to logout/login to updates new permissions;
    How can I change this and system always query in database for permissions?
    Thanks for your help.

  24. Hi there,

    I’m trying to adapt this for a Asp.Net Core Web API.
    Most of it seems to work, I’m just having trouble with the `AuthorizeAsync` call.

    On the authorization service, there is no signature that allow me to just pass a User+permission(as string). I’m directly expected to provide an `AuthorizationPolicy` here. Should I inject myself the `IAuthorizationPolicyProvider`, build the `AuthorizationPolicy` and provide to the `AuthorizeAsync` method, or am I missing something?

    Thanks

  25. Hi man
    First of all, great content!
    Could you please show how can i change default user id wich is string into int?

  26. Great, I learned a lot, before that I did not know what, there is such a thing as permission exists