Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get params from AuthorizationHandler .NET Core

I am using an authorization handler to put custom authorization in my controller in .net core. How can I get the parameters from the controller and use it to the authorization handler?

In the old .NET I can get the parameters from HttpContext request param like this:

var eventId = filterContext.RequestContext.HttpContext.Request.Params["id"];

I am not sure how can I achieved it in .net core

public class HasAdminRoleFromAnySiteRequirement : AuthorizationHandler<HasAdminRoleFromAnySiteRequirement>, IAuthorizationRequirement
{
    public HasAdminRoleFromAnySiteRequirement()
    {

    }

    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
        HasAdminRoleFromAnySiteRequirement requirement)
    {   

    //need to call get param from controller to used in the validation
    // something like this 
    //var eventId = filterContext.RequestContext.HttpContext.Request.Params["id"];
   // I tried the suggestion below but I can't get the parameter from routedata
   // var mvcContext = context.Resource as     Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext;            

        return Task.FromResult(0);
    }
}
like image 412
Ramppy Dumppy Avatar asked Sep 20 '16 08:09

Ramppy Dumppy


People also ask

What is HttpContextAccessor .NET core?

It stores the request and response information, such as the properties of request, request-related services, and any data to/from the request or errors, if there are any. ASP.NET Core applications access the HTTPContext through the IHttpContextAccessor interface. The HttpContextAccessor class implements it.

What is FromBody in asp net core?

[FromBody] attributeThe ASP.NET Core runtime delegates the responsibility of reading the body to an input formatter. Input formatters are explained later in this article. When [FromBody] is applied to a complex type parameter, any binding source attributes applied to its properties are ignored.

What is policy based authorization?

Authorization Policy Even when you use claim-based or role-based authorization, you are actually using Policy-based Authorization. A Policy defines a collection of requirements, that the user must satisfy in order to access a resource. The user must satisfy all the requirements.


3 Answers

In ASP.NET Core 3.0 with endpoint routing enabled, you can get a route parameter value like this:

public class MyRequirementHandler : AuthorizationHandler<MyRequirement>
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    public MyRequirementHandler(IHttpContextAccessor httpContextAccessor)
    {
       _httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor));
    }

    protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, MyRequirement requirement)
    {
        var routeData = _httpContextAccessor.HttpContext.GetRouteData();

        var areaName = routeData?.Values["area"]?.ToString();
        var area = string.IsNullOrWhiteSpace(areaName) ? string.Empty : areaName;

        var controllerName = routeData?.Values["controller"]?.ToString();
        var controller = string.IsNullOrWhiteSpace(controllerName) ? string.Empty : controllerName;

        var actionName = routeData?.Values["action"]?.ToString();
        var action = string.IsNullOrWhiteSpace(actionName) ? string.Empty : actionName;

        //...
    }
}
like image 179
VahidN Avatar answered Oct 04 '22 18:10

VahidN


In your handler you can do the following

var mvcContext = context.Resource as 
    Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext;

if (mvcContext != null)
{
    // Examine MVC specific things like routing data.
}

If you want parameter values then the authorize attribute pieces run before binding has taking place. Instead you would move to an imperative call, inside your controller. This is basically resource based authorization, your parameter is a resource.

You would inject the authorization service into your controller;

public class DocumentController : Controller
{
    IAuthorizationService _authorizationService;

    public DocumentController(IAuthorizationService authorizationService)
    {
        _authorizationService = authorizationService;
    }
}

Then write your handler slightly differently;

public class DocumentAuthorizationHandler : AuthorizationHandler<MyRequirement, Document>
{
    public override Task HandleRequirementAsync(AuthorizationHandlerContext context,
                                                MyRequirement requirement,
                                                Document resource)
    {
        // Validate the requirement against the resource and identity.

        return Task.CompletedTask;
    }
}

You can see this handler takes a document, this can be whatever you like, be it an integer for an ID, or some type of view model.

Then you have access to it inside your HandleRequirementAsync() method.

Finally, you'd call it from within your controller, once binding has taken place;

if (await authorizationService.AuthorizeAsync(
    User, 
    document,     
    yourRequirement))
{
}
like image 39
blowdart Avatar answered Oct 04 '22 18:10

blowdart


In ASP.NET Core 2.2, you can get a route parameter value like this:

public class MyRequirementHandler : AuthorizationHandler<MyRequirement>
{
    protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, MyRequirement requirement)
    {
        var authContext = (AuthorizationFilterContext)context.Resource;
        var routeValueOfX = authContext.HttpContext.GetRouteValue("X");
        .
        .
        .
    }
}
like image 17
Tohid Avatar answered Oct 03 '22 18:10

Tohid