Base solution for your next web application
Open Closed

Override Role/Permissions #12483


User avatar
0
klpattison created

I have added a NewUser table which links to AbpUsers so that I can have the same user with a single email have multiple profiles in the system. Then I added a NewUserRole table so that each profile can have different roles/permissions. How can I override the default authorization to use the NewUserRole vs AbpUserRoles table.

Markdown is supported
Copy & paste or drag & drop images (max 30 MB per image)

3 Answer(s)
  • User Avatar
    0
    oguzhanagir created
    Support Team

    Hi @klpattison

    To achieve your goal of using a custom NewUserRole table for authorization in your ASP.NET Zero project, you need to intercept and replace the framework's default permission checking logic.

    The central component you must override is the PermissionChecker class. You will need to create your own class that inherits from it and provides new logic for the IsGrantedAsync method.

    Inside your custom implementation, instead of letting the base method run, your new logic should:

    • Get the current user's ID from the session.
    • Identify which of the user's multiple profiles (NewUser) is currently active for the session.
    • Based on that active profile's ID, query your custom NewUserRole table.
    • Determine if any of the roles assigned to that profile have been granted the specific permission being checked.

    Your application must be aware of which profile is currently active. The best way to handle this is to modify your login process.

    After a user authenticates, you should prompt them to select a profile if they have more than one. Once a profile is selected, you must store its unique identifier (your NewUserId) as a custom claim within the user's session token (JWT). By doing this, the active profile ID will be securely available throughout the application via the AbpSession.

    After creating your custom permission checker, you need to tell the application's Dependency Injection system to use it instead of the default one.

    This is done in the PreInitialize method of your CoreModule (the YourProjectNameCoreModule.cs file). You will use the Configuration.ReplaceService method to replace the default IPermissionChecker interface with your new custom class.

    When you grant or revoke a role from one of your user profiles, the application will not recognize this change immediately. This is because the user's permissions are stored in a cache for fast access. You must manually clear this cache after making a change. Using the global cache manager, ICacheManager, it finds and clears the specific cache where user privileges are held.

    For detailed information on how to implement these changes, refer to the official ASP.NET Boilerplate documentation, which is the foundation for ASP.NET Zero.

    ABP Documentation - Authorization

    ABP Documentation - Replacing Services

    ABP Documentation - Create Custome Session

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    klpattison created

    Thanks for the detailed reply. This aligns with the method I have been trying but I can not get the system to pick up the new PermissionChecker.

    I have implemented a new MyAppPermisionChecker class in MyApp.Core ->Authorization folder

    public class MyAppPermissionChecker : PermissionChecker<Role, User>
    {
        private readonly IRepository<TgpActiveUser> _tgpActiveUserRepository;
        private readonly IRepository<TgpUserRole> _tgpUserRoleRepository;
        private readonly IRepository<Role> _roleRepository;
        private readonly PermissionManager _permissionManager;
        private readonly RoleManager _roleManager;
        private readonly UserManager _userManager;
    
        public TgpPermissionChecker(
            UserManager userManager,
            RoleManager roleManager,
            PermissionManager permissionManager,
            IRepository<TgpActiveUser> tgpActiveUserRepository,
            IRepository<TgpUserRole> tgpUserRoleRepository,
            IRepository<Role> roleRepository)
            : base(userManager)
        {
            _userManager = userManager;
            _roleManager = roleManager;
            _permissionManager = permissionManager;
            _tgpActiveUserRepository = tgpActiveUserRepository;
            _tgpUserRoleRepository = tgpUserRoleRepository;
            _roleRepository = roleRepository;
        }
    
    
        public override async Task<bool> IsGrantedAsync(long userId, string permissionName)
       
    

    Then in MyApp.Core->MyAppCoreModule.cs I have added the line:

        Configuration.ReplaceService<IPermissionChecker, TgpPermissionChecker>(DependencyLifeStyle.Transient);
    

    The issue I am having is the IsGrantedAsync call in my new class never gets called.

    I have tried a lot of different things but if you can provide any suggestions on this, that would be great.

    Thanks,

    Kevin

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    oguzhanagir created
    Support Team

    Hi @klpattison

    The PermissionChecker class is located under the Authorization folder within the *.Core project. Permission checking operations are performed using this class, and in the IdentityRegistrar, the AddPermissionChecker method uses this class to register the service. If you intend to use your custom PermissionChecker class, you need to specify it as the generic type in the AddPermissionChecker method within the static IdentityRegistrar class. Additionally, you must update all usages of the original PermissionChecker to use your custom implementation.

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)