How create custom authorization attribute for checking a role and url path in Asp.Net Core?
Asked Answered
C

2

6

I want to create a custom authorization attribute for checking the role and url path.

I've find the way for doing it in the Asp.Net Core using the Policy-Based-Authorization but I've tried implement it but I can't get the HttpContext with incomming url.

AuthorizationHandlerContext hasn't access to HttpContext probable.

How can I get current HttpContext with the url path? Is it possible to do that or with another way?

I've tried this code for creating the custom Policy:

public class RoleUrlValidationHandler : AuthorizationHandler<RoleUrlValidationRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, RoleUrlValidationRequirement requirement)
    {           
        var path = //Here I need get current url path for example - /api/posts/4545411
        var pathPart = path.Split('/');
        var clientId = pathPart[3];

        if (context.User.IsInRole(clientId))
        {
            context.Succeed(requirement);
        }

        return Task.CompletedTask;
    }
}

I want to create following:

[Authorize(Policy="RoleUrlValidation")] //Get ClientId from Url and check User's roles
public class PostsController : Controller
{
    public ActionResult Get()
    {
    }
}
Cerracchio answered 8/1, 2017 at 14:44 Comment(3)
Frist you are not supposed to implement own Autzorize attributes. The approach with Policies is correct. Second you can use DI inside the handlersTroll
@Troll Sorry, What do you mean "not supposed to implement own Autzorize attributes." and Why?Ables
@b.ben: ASP.NET Core team made certain methods on AuthorizeAttribute method non-virtual (or removed them), means you can't override them anymore (like it used to work in legacy ASP.NET). They introduced the policy based authorization as replacement, since its more flexible and easier for 3rd parties to add new policies, see this answer from blowdart, the developer responsible for ASP.NET Core securityTroll
T
12

The policy approach is the right one. Only bit you missed is, that you can use Dependency Injection in the Handlers.

public class RoleUrlValidationHandler : AuthorizationHandler<RoleUrlValidationRequirement>
{
    private readonly IHttpContextAccessor contextAccessor;

    public RoleUrlValidationHandler(IHttpContextAccessor contextAccessor)
    {
        this.contextAccessor = contextAccessor;
    }

    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, RoleUrlValidationRequirement requirement)
    {
        var httpContext = contextAccessor.HttpContext;
        var path = httpContext.Request.Path;
        var pathPart = path.Split('/');
        var clientId = pathPart[3];

        if (context.User.IsInRole(clientId))
        {
            context.Succeed(requirement);
        }

        return Task.CompletedTask;
    }
}

You also may have to register the IHttpContextAccessor as its not registered by default.

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

Extra bits:

Consider using var routeData = httpContext.GetRouteData() instead of using path.Split('/') for reading values from it so you can easily read the parameter values from the route.

Troll answered 8/1, 2017 at 15:1 Comment(3)
It looks amazing. I'll try it. Yes, you're correct, I missed the DI possibilty for doing that. :-) Thanks.Cerracchio
Do you mean httpContext.GetRouteData(); probable?Cerracchio
Yea, right. Wasn't really related to the code above, just a generalized form. But will fix it to avoid confusionTroll
H
0

Try like this:

((DefaultHttpContext)context.Resource).Request.Path.Value
Hyperpituitarism answered 16/2, 2022 at 9:19 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Cocoa

© 2022 - 2024 — McMap. All rights reserved.