0

I am trying to make a custom authorization system I am following the answer given by Shawn here How do you create a custom AuthorizeAttribute in ASP.NET Core?. However, I have a problem getting it to work.

Here are my custom class for the authorization

    public abstract class AttributeAuthorizationHandler<TRequirement, TAttribute> : AuthorizationHandler<TRequirement> where TRequirement : IAuthorizationRequirement where TAttribute : Attribute
    {
        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, TRequirement requirement)
        {
            var attributes = new List<TAttribute>();

            var action = (context.Resource as AuthorizationFilterContext)?.ActionDescriptor as ControllerActionDescriptor;
            if (action != null)
            {
                attributes.AddRange(GetAttributes(action.ControllerTypeInfo.UnderlyingSystemType));
                attributes.AddRange(GetAttributes(action.MethodInfo));
            }

            return HandleRequirementAsync(context, requirement, attributes);
        }

        protected abstract Task HandleRequirementAsync(AuthorizationHandlerContext context, TRequirement requirement, IEnumerable<TAttribute> attributes);

        private static IEnumerable<TAttribute> GetAttributes(MemberInfo memberInfo)
        {
            return memberInfo.GetCustomAttributes(typeof(TAttribute), false).Cast<TAttribute>();
        }
    }


    public class PermissionAttribute : AuthorizeAttribute
    {
        public string Name { get; }

        public PermissionAttribute(string name) : base("Permission")
        {
            Name = name;
        }
    }

    public class PermissionAuthorizationHandler : AttributeAuthorizationHandler<PermissionAuthorizationRequirement, PermissionAttribute>
    {
        private readonly IEmployeeService _employeeMenuService;

        public PermissionAuthorizationHandler(IEmployeeService employeeMenuService)
        {
            _employeeMenuService = employeeMenuService;
        }


        protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionAuthorizationRequirement requirement, IEnumerable<PermissionAttribute> attributes)
        {
            foreach (var permissionAttribute in attributes)
            {
                if (!await AuthorizeAsync(context.User, permissionAttribute.Name))
                {
                    return;
                }
            }

            context.Succeed(requirement);
        }

I believe that changes the return true to return false would block the page but it does not work.

        private async Task<bool> AuthorizeAsync(ClaimsPrincipal user, string permission)
        {
            //Implement your custom user permission logic here

            await _employeeMenuService.GetAllEmployees();

            return true; 
        }
    }
    public class PermissionAuthorizationRequirement : IAuthorizationRequirement
    {
        //Add any custom requirement properties if you have them
    }

Here is the controller that I want to block

    [Permission("fichacliente")]
    public class fichaClienteController : Controller
    {
    }

Finaly here is my startup code.

            services.AddTransient<IAuthorizationHandler, PermissionAuthorizationHandler>();

            services.AddAuthorization(options =>
            {
                options.AddPolicy("Permission", policyBuilder =>
                {
                    policyBuilder.Requirements.Add(new PermissionAuthorizationRequirement());
                });
            });
Vy Do
  • 46,709
  • 59
  • 215
  • 313
J.C
  • 632
  • 1
  • 10
  • 41
  • 1
    You have return true; it cases your problem – Serge Jul 09 '21 at 18:09
  • When I set the return true to return false It still pases. @Serge wich is my problem. – J.C Jul 09 '21 at 18:15
  • 1
    Try calling `context.Fail()` explicitly because returning isn't the same as failing an authorization requirement. Returning, so to speak, is just a way for a handler to say "I couldn't authorize the user, let the next handler handle things". – Dennis VW Jul 09 '21 at 20:48
  • I Think I am geting closer to the answer. Thanks to you @Dennis1679. Howver when I force the context.Fail() I get the following error InvalidOperationException: No authenticationScheme. Should I not get a 403 error instead? – J.C Jul 09 '21 at 20:59
  • Thank you @Dennis1679 it works now I only had to change the lauchSettings.json file and set "windowsAuthentication": true, – J.C Jul 09 '21 at 21:19

0 Answers0