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);
}
}
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.
[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.
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.
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;
//...
}
}
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))
{
}
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");
.
.
.
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With