4
votes

I am migrating a web API from .net Framework to .net Core. The old version was able to ignore the Authorize Attribute on the controller if the app was running on a private server. Here is the code for that. I know .net core 3.1 does not offer Custom AuthorizeAttributes. That is not my question.

// A custom AuthroizeAttribute
public class ConditionalAuthorizeAttribute : AuthorizeAttribute
{

    protected override bool IsAuthorized(HttpActionContext httpContext)
    {
        if (environment_private())
            return true;
        else
            return base.IsAuthorized(httpContext);
    }


    private bool environment_private()
    {
        // code that will tell you if you are in your dev environment or not
        return Properties.Settings.Default.PrivateServer;
    }
}

// How it was called from the controller
[ConditionalAuthorize(Roles = "MyRole")]
[Route(...)]
// More code for controller

I just need a simple way to authorized all requests when running the project on our private server (which is determined by a variable in appSettings.json). I have tried policies, but I face the following difficulties:

1) I couldn't pass the variable in the configuration from the controller to a parameterized authorize attribute.
2) I couldn't inject the configuration into a parameterized authorize attribute.

This effectively eliminated my ability to follow this guide in any way: https://docs.microsoft.com/en-us/aspnet/core/security/authorization/iauthorizationpolicyprovider?view=aspnetcore-2.2

This leads to my question: How can I use a value from appSettings.json to override whether the request checks a role or not?

1

1 Answers

4
votes

After a lot of research, I found a way to do it using TypeFilterAttribute. Essentially, it's the same way of doing it (using a custom attribute to filter all requests and check the condition within the custom attribute) except I used .net Core-supported methods.

In case you are trying to solve this same issue, here are the exact steps to my solution.

  1. Add two files, "YourAttributeNameAttribute.cs" and "YourFilterNameFilter.cs".
  2. In the "YourAttributeNameAttribute.cs" file, the code is as follows:
public class YourAttributeNameAttribute : TypeFilterAttribute
{
    public YourAttributeNameAttribute(string role) : base(typeof(YourFilterNameFilter))
    {
        Arguments = new object[] { role };
    }
}
  1. The code in "YourFilterNameFilter.cs":
public class YourFilterNameFilter : IAuthorizationFilter
{
    private readonly string Role;
    public YourFilterNameFilter(string role)
    {
        Role = role;
    }
    public void OnAuthorization(AuthorizationFilterContext context)
    {
        var configuration = context.HttpContext.RequestServices.GetService<IConfiguration>();

        // If private server, ignore roles
        if (private_server_logic_here)
            return;

        var user = context.HttpContext.User;

        // Check role if on public server
        if (!user.IsInRole(Role))
        {
            context.Result = new StatusCodeResult((int)System.Net.HttpStatusCode.Unauthorized);
            return;
        }
    }
}
  1. The code for the controller:
[YourAttributeName("role_name")]
[Route("api/my_route")]
[HttpGet]