Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass parameters to a Requirement/Policy in ASP.NET MVC 6

I was trying to make a custom authorization attribute in ASP.NET vNext, until I found this excelent answer from @blowdart in this post:

https://stackoverflow.com/a/31465227/1756978

indicating that Authorization requirements is now the way to go. The answer is very clarifying but doesn't indicates how to pass a parameter to this requirements / policies.

What I'm trying to do is porting a MVC 5 custom authorization attribute which has this signature:

[Autorizacion(Requires = enumPermission.DeleteCustomer)]

since I use a very customised set of permissions mirrored in the backend/frontend as enums/strings.

As this features are still not documented I feel a little lost... Could anybody give guidance about?

Thanks in advance

like image 252
Vi100 Avatar asked Aug 24 '15 11:08

Vi100


1 Answers

I happen to comes up with a workround that can satisfy my requirement, hope it will help your too.

In my case, I need to pass IHttpContextAccessor and EFCore's AppDbContext to my Requirement class.

in my Startup.cs, I write something like this:

services.AddAuthorization(options =>
{
    options.AddPolicy("ThePolicy", policy => policy.Requirements.Add( new ThePolicyRequirement() ));
});
services.AddScoped<IAuthorizationHandler, ThePolicyAuthorizationHandler>();

the ThePolicyAuthorizationHandler class:

public class ThePolicyAuthorizationHandler : AuthorizationHandler<ThePolicyRequirement>
{
    readonly AppDbContext _appContext;
    readonly IHttpContextAccessor _contextAccessor;

    public ThePolicyAuthorizationHandler(AppDbContext c, IHttpContextAccessor ca)
    {
        _appContext = c;
        _contextAccessor = ca;
    }

    protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, ThePolicyRequirement requirement)
    {
        var result = await requirement.isPass(_appContext, _contextAccessor, context);
        if (result)
            context.Succeed(requirement);
        else
            context.Fail(requirement);
    }
}

and ThePolicyRequirement class:

public class ThePolicyRequirement : IAuthorizationRequirement
{
    AppDbContext _context;
    IHttpContextAccessor _contextAccessor;
    AuthorizationHandlerContext _authHandlerContext;

    public async Task<bool> isPass(AppDbContext context, IHttpContextAccessor contextAccessor, AuthorizationHandlerContext authorizationHandlerContext)
    {
        _context = context;
        _contextAccessor = contextAccessor;
        _authHandlerContext = authorizationHandlerContext;

        //logic here

        return result;
    }
}

The key idea is using ThePolicyAuthorizationHandler to obtain as much as possible all needed objects, and pass it to ThePolicyRequirementto do the logic of the authorization mechanism.

like image 136
Riza Avatar answered Oct 20 '22 06:10

Riza