Home > Enterprise >  Passing arguments to IAsyncAuthorizationFilter inside TypeFilterAttribute
Passing arguments to IAsyncAuthorizationFilter inside TypeFilterAttribute

Time:06-23

I'm trying to pass arguments to an IAsyncAuthorizationFilter filter from the TypeFilterAttribute. I made a simple example which according to answers such as this one https://stackoverflow.com/a/44435070/937131 should work.

public class SimpleAuthorizeServiceAttribute : TypeFilterAttribute
{
    public SimpleAuthorizeServiceAttribute(string service, string context, AccessType access) : base(typeof(SimpleAuthorizeServiceAttribute))
    {
        Arguments = new[] { new PermissionData(service, context, access) };
    }

    public class SimpleAuthorizeServiceFilter : IAsyncAuthorizationFilter
    {
        private readonly PermissionData _permissionData;

        public SimpleAuthorizeServiceFilter(PermissionData permissionData)
        {
            _permissionData = permissionData;
        }

        public virtual Task OnAuthorizationAsync(AuthorizationFilterContext context)
        {
            var test = _permissionData.Service != null;
            return Task.CompletedTask;
        }
    }
}

I've then applied this to a method like this:

[HttpGet]
[SimpleAuthorizeService("test-service", "test-context", AccessType.Read)]
public async Task<bool> ServiceTest()
{
    bool isAllowed = this.HttpContext.IsUserAllowedToAccess(10, 20, 30);
    return isAllowed;
}

Which fails with

System.InvalidOperationException: A suitable constructor for type 'SecurityAttribute.Application.ServiceToServiceAttribute.SimpleAuthorizeServiceAttribute' could not be located. Ensure the type is concrete and all parameters of a public constructor are either registered as services or passed as arguments. Also ensure no extraneous arguments are provided.

I thought this might be because I'm not using params for the TypeFilterAttribute (which is dumb). So i rewrote it to this monstrosity..

public class SimpleAuthorizeServiceAttribute : TypeFilterAttribute
{
    public SimpleAuthorizeServiceAttribute(params string[] data) : base(typeof(SimpleAuthorizeServiceAttribute))
    {
        // hoorray for non type safe paramaters...
        var success = AccessType.TryParse(data[2], out AccessType access);
        Arguments = new[] { new PermissionData(data[0], data[1], access) };
    }

    public class SimpleAuthorizeServiceFilter : IAsyncAuthorizationFilter
    {
        private readonly PermissionData _permissionData;

        public SimpleAuthorizeServiceFilter(PermissionData permissionData)
        {
            _permissionData = permissionData;
        }

        public virtual Task OnAuthorizationAsync(AuthorizationFilterContext context)
        {
            var test = _permissionData.Service != null;
            return Task.CompletedTask;
        }
    }
}
    ....
     
[HttpGet]
[SimpleAuthorizeService("test-service", "test-context", "Read")]
public async Task<bool> ServiceTest()
{
   bool isAllowed = this.HttpContext.IsUserAllowedToAccess(10, 20, 30);
   return isAllowed;
}

But that still trows an error:

System.InvalidOperationException: A suitable constructor for type 'SecurityAttribute.Application.ServiceToServiceAttribute.SimpleAuthorizeServiceAttribute' could not be located. Ensure the type is concrete and all parameters of a public constructor are either registered as services or passed as arguments. Also ensure no extraneous arguments are provided. at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.FindApplicableConstructor(Type instanceType, Type[] argumentTypes, ConstructorInfo& matchingConstructor, Nullable`1[]& matchingParameterMap)

So how is one supposed to pass arguments to a IAsyncAuthorizationFilter?

CodePudding user response:

The issue is with this line

    public SimpleAuthorizeServiceAttribute(string service, string context, AccessType access) : 
base(typeof(SimpleAuthorizeServiceAttribute)) // problem is here
    {
        Arguments = new[] { new PermissionData(service, context, access) };
    }

it should be SimpleAuthorizeServiceFilter not SimpleAuthorizeServiceAttribute.

replace it and it should work.

  • Related