Home > OS >  In ASP.NET Core, how do I extend the default Roles-based authorization without having to create my o
In ASP.NET Core, how do I extend the default Roles-based authorization without having to create my o

Time:01-21

In ASP.NET Core 6 , if I want my own way of authorizing, it seems that I should implement an IAuthorizationRequirement and a handler that inherits from AuthorizationHandler<T> for that requirement, then use it via policy. I did that just fine and it works.

I'd like to have some users who can still be authorized by role or be authorized based on other requirements.

So therefore, I want to retain the default roles-based authorization but in my handler in some cases alter the roles before authorization-proper happens. Can I somehow compose it--perhaps call the default roles-based handler from my handler? Or would I need to re-implement everything the default handler does--and if so, how?

None of the examples I can find seem to attempt this--they all seem to implement their own thing from scratch, not paying attention to roles at all.

So how do I extend the default Roles-based authorization without having to implement my own full handler from scratch?

CodePudding user response:

I'd like to have some users who can still be authorized by role but have additional restrictions based on such requirements.

Role-based authorization could work together with Policy-based Authorization

Add the Authorize Attribute like:[Authorize(Role="SomeRole",Policy="SomePolicy")]

or regist the policy like:

    builder.Services.AddAuthorization(options => 
     {   
       options.AddPolicy("RequireAdministratorRoleWithSomeOtherRequirement",policy 
      => 
         {
           policy.RequireRole("Administrator")); 
           policy.AddRequirement(new SomeRequirement(input));
         });
options.AddPolicy("AnotherPolicy",policy 
      => 
         {
           policy.RequireRole("Administrator","OtherRoles")); 
           policy.AddRequirement(new OtherRequirement(input));
         });
     });

CodePudding user response:

I wanted to do this with a new policy, but I could not figure out how, as even if I inherit my new AuthorizationRequirement from RolesAuthorizationRequirement, and then implement everything needed to replace the default handler, I'd still have to provide the roles to the requirement when I AddPolicy in Program.cs, which I don't have.

Luckily, my need does not require any additional data in a new AuthorizationRequirement class, so I can forgo that and just totally override the default handler. So, in Program.cs:

builder.Services
    .AddAuthorization() 
    .AddSingleton<IAuthorizationHandler, NonproductionAuthorizeHandler>() // note this makes NonproductionAuthorizeHandler override the default handler
    ...

And the new handler:

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authorization.Infrastructure;

namespace MyNamespace.Server.Helpers;

/// <summary>
/// Handles authorization to allow access to attribute-specified roles in any environment,
/// as well as special logic that need not be specified in
/// any AuthorizationAttribute (which may appear on any controller or controller method). 
/// </summary>
public class SpecialLogicAuthorizeHandler : AuthorizationHandler<RolesAuthorizationRequirement>
{
    private readonly IWebHostEnvironment environment;

    public SpecialLogicAuthorizeHandler(/* optional injected dependencies */) {}

    protected override Task HandleRequirementAsync(
        AuthorizationHandlerContext context,
        RolesAuthorizationRequirement requirement)
    {
        if (requirement.AllowedRoles.Any(context.User.IsInRole) || IsAllowedBySpecialLogic())
        {
            context.Succeed(requirement);
        }       
        return Task.CompletedTask;
    }

    private bool IsAllowedBySpecialLogic(){
        // whatever you want here
    }
}

With that, it is always effective for all AuthorizationAttributes and no policy is needed.

[Authorize(Roles = "MyRole1")]
[HttpGet]
public async Task<string> Get(){
   ... 
}
/// the user can access the above if they satisfy the special logic OR if they are in MyRole1. 
  • Related