2

I am working on different applications each of which has its own role members.

In Startup.cs

var c= _configuration.GetSection(nameof(Configuration)).Get<List<Configuration>>();
foreach (Configuration r in c)
{
   services.AddAuthorization(options => {
                   options.AddPolicy(Configuration.Role, policy => 
                       policy.RequireRole(r.RoleMembers.Split(",")));
                   });
}

The below code doesn't work as I am referring to an array.

[Authorize(Policy = Configuration.Role)]

How can I authorize against the 0th element?

Chris Stillwell
  • 10,266
  • 10
  • 67
  • 77
user215
  • 65
  • 1
  • 6
  • 1
    What are `Configuration.Role` and `authorize against the 0th element`?Could you be more specific about your requirement? – Ryan Oct 08 '19 at 05:10

2 Answers2

3

You could implement your custom AuthorizeAttribute for multiple policies.

1.AuthorizeMultiplePolicyAttribute

public class AuthorizeMultiplePolicyAttribute : TypeFilterAttribute
{
    public AuthorizeMultiplePolicyAttribute(string[] policies) : base(typeof(AuthorizeMultiplePolicyFilter))
    {
        Arguments = new object[] { policies };
    }
}

2.AuthorizeMultiplePolicyFilter

public class AuthorizeMultiplePolicyFilter : IAsyncAuthorizationFilter
{
    private readonly IAuthorizationService _authorization;
    public string[] _policies { get; private set; }

    public AuthorizeMultiplePolicyFilter(string[] policies,IAuthorizationService authorization)
    {
        _policies = policies;
        _authorization = authorization; 
    }

    public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
    {
            foreach (var policy in _policies)
            {
                var authorized = await _authorization.AuthorizeAsync(context.HttpContext.User, policy);
                if (!authorized.Succeeded)
                {
                    context.Result = new ForbidResult();
                    return;
                }
            }

    }
}

3.Add Policy you want on Startup one by one

services.AddAuthorization(options =>
{
   //register all policies based on your own code,give them different policy name
    options.AddPolicy("AdminPolicy", policy =>
            policy.RequireRole("Admin"));

    options.AddPolicy("SuperPolicy", policy =>
            policy.RequireRole("Super"));
});

4.Use the custom attribute

[AuthorizeMultiplePolicy(new string[] { "AdminPolicy", "SuperPolicy" })]
Ryan
  • 19,118
  • 10
  • 37
  • 53
  • thank you but the reason why i have used foreach is because the policy is different for different applications. Can i differentiate based on the application ID. – user215 Oct 08 '19 at 14:57
  • @vani s Yes,just remember to the policies' names are different and register them using foreach.My answer does not care how you register the policies but the way to use multiple policies with custom Authorize attribute. – Ryan Oct 09 '19 at 01:12
  • A similar solution can be found in https://stackoverflow.com/questions/51443605/how-to-include-multiple-policies/ and https://stackoverflow.com/questions/52628473/how-to-add-multiple-policies-in-action-using-authorize-attribute-using-identity – Terence Golla Sep 24 '21 at 21:15
0

I admit I have never tried something like this before, but I am pretty certain the policies have to have a name and the authorize attribute would reference that.

Maybe something like this would work if each config entry you are looping through had an identifier field, in this case I name it title.

var c= _configuration.GetSection(nameof(Configuration)).Get<List<Configuration>>();
foreach (Configuration r in c)
{
   services.AddAuthorization(options => {
                   options.AddPolicy("RolePolicy" + r.title, policy => 
                       policy.RequireRole(r.RoleMembers.Split(",")));
                   });
}

I think your split call on rolemembers would work, but I haven't tried it.

And assuming the title for one of the entries in the config section was "AdminOnly"

[Authorize(Policy = "RolePolicyAdminOnly")]

I think that will give you what you want.

Edit: Actually I take it back, I think the split to expand the rolemembers will fail since it has to be a comma delimited list of string and the comma not in the string. I am not sure this can be defined from the config. You may need to look into IAuthorizationService and moving your entries outside of the config.

Ben Matthews
  • 499
  • 2
  • 5