0

I'm using ASP.NET Core 2.2 and I have a custom Authorize attribute filter called CustomAuthorize that handles authentication and authorization. The authentication part is handled manually with some code I've written in the OnAuthorization function, and the authorization part is taken care of by whatever code is in the AuthorizeAttribute class, which CustomAuthorize inherits from.

I want to be able to inject several services into my CustomAuthorize filter in order to verify that the user's roles have not been changed in the database by comparing them to those in the Role claims. I found that the way to inject services is to use the ServiceFilterAttribute. When I apply the ServiceFilter to the CustomAuthorize attribute like this:

enter image description here

I get the error The name 'Roles' does not exist in the current context. I understand that ServiceFilter can't accept constructor arguments for the type (that's the TypeFilter's job) but Role is just a property on the AuthorizeAttribute class, as you can see below:

enter image description here

public class AuthorizeAttribute : Attribute, IAuthorizeData
{
    public AuthorizeAttribute();
    public AuthorizeAttribute(string policy);

    public string Policy { get; set; }
    public string Roles { get; set; }
    public string AuthenticationSchemes { get; set; }
    public string ActiveAuthenticationSchemes { get; set; }
}

So, why can't I set the Roles property for the attribute filter? What am I misunderstanding here?

My CustomAuthorize filter. I would eventually have a constructor and inject my services into it:

public class CustomAuthorize : AuthorizeAttribute, IAuthorizationFilter
    {
        public void OnAuthorization(AuthorizationFilterContext context)
        {
            string redirectUrl = "/UserAccess/Index";

            if (context.HttpContext.User.Identity.IsAuthenticated)
            {
                if (context.HttpContext.User.HasClaim(CustomClaimTypes.UserNotFound, true.ToString()))
                {
                    context.Result = new RedirectResult("/UserAccess/NotAuthorized");
                }
            }
            else
            {
                if (context.HttpContext.Request.IsAjaxRequest())
                {
                    context.HttpContext.Response.StatusCode = 401;

                    JsonResult jsonResult = new JsonResult(new { redirectUrl = redirectUrl });
                    context.Result = jsonResult;
                }
                else
                {
                    context.Result = new RedirectResult(redirectUrl);
                }
            }
        }
    }

Lukas
  • 1,699
  • 1
  • 16
  • 49
  • You're using invalid syntax. `typeof` takes a type. You're passing it a call to method named `CustomAuthorize` in which you're attempting to assign a string to a property named `Roles` in the enclosing scope, passing the result of that assignment as the first argument to that function. – Aluan Haddad Sep 04 '20 at 14:15
  • Did you mean `[ServiceFilter(typeof(CustomAuthorize), new[] { "Processor", "Global Admin" })]`? – Aluan Haddad Sep 04 '20 at 14:21
  • Thank you for the responses. I think I understand your explanation of why the syntax is invalid, but the suggested syntax is not quite what I'm trying to do, as it is trying pass two arguments to the constructor of the `ServiceFilter` when I'm trying to set the `Roles` property on the `CustomAuthorize` attribute. `ServiceFilter` only accepts a single argument of `Type` and does not have a `Roles` property. All of this is making me think what I'm trying to do might not be possible with dependency injection. – Lukas Sep 04 '20 at 14:36
  • What you're doing doesn't interact with dependency injection. The documentation for type filter is clear about that. If you read that documentation thoroughly, you'll see that the code I suggested is proper because of how it specifies its API. It takes the type of the attribute, and then a list of the parameters that will use to construct that attribute reflectively. Attribute arguments that can be specified when applying an attribute are confined to a highly restrictived subset of .NET values. I suggest you study attributes – Aluan Haddad Sep 04 '20 at 14:41
  • I see my mistake, I was looking at the documentation for type filter not service filter. You're correct, you can't forward arguments – Aluan Haddad Sep 04 '20 at 14:46

0 Answers0