44

How can I access current HttpContext to check for route and parameters inside AuthorizationHandlerContext of Custom Policy-Based Authorization inside ASP.NET Core 2?

Ref example: Custom Policy-Based Authorization

5 Answers 5

90

You should inject an instance of an IHttpContextAccessor into your AuthorizationHandler.

In the context of your example, this may look like the following:

public class BadgeEntryHandler : AuthorizationHandler<EnterBuildingRequirement>
{
    IHttpContextAccessor _httpContextAccessor = null;

    public BadgeEntryHandler(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    protected override Task HandleRequirementAsync(
        AuthorizationContext context, 
        EnterBuildingRequirement requirement)
    {
        HttpContext httpContext = _httpContextAccessor.HttpContext; // Access context here

        if (context.User.HasClaim(c => c.Type == ClaimTypes.BadgeId &&
                                       c.Issuer == "http://microsoftsecurity"))
        {
            context.Succeed(requirement);
            return Task.FromResult(0);
        }
    }
}

You may need to register this in your DI setup (if one of your dependencies has not already), as follows:

services.AddHttpContextAccessor();
Sign up to request clarification or add additional context in comments.

3 Comments

Ok, and what is best way to extract HTTP GET parameter (from route, like route="/api/customers/{customerGuid}" ) without manually parsing the string Path from HttpContext? Tx
@HrvojeKusulja: The parameter values are not bound at this stage (even for an IActionContextAccessor). You may need to do something simillar to what is detailed in this post - How to get params from AuthrizationHandler .net core. The author of this answer is the ASP.NET security guy at Microsoft, so it is authoritative. Whether things have moved on since this post I cannot be sure. Note: I have updated my post with detail regarding DI registration (it may be required).
This is the best way to do it for anyone working with custom handlers, as you shouldn't rely on resource object, unless you know what's going to be in it. If you use the IAuthorizationService to invoke authorization, you can pass anything in the resource.
8

This is from Microsoft docs (for ASP.NET Core 6):

The HandleRequirementAsync method has two parameters: an AuthorizationHandlerContext and the TRequirement being handled. Frameworks such as MVC or SignalR are free to add any object to the Resource property on the AuthorizationHandlerContext to pass extra information.

When using endpoint routing, authorization is typically handled by the Authorization Middleware. In this case, the Resource property is an instance of HttpContext. The context can be used to access the current endpoint, which can be used to probe the underlying resource to which you're routing. For example:

if (context.Resource is HttpContext httpContext) {
    var endpoint = httpContext.GetEndpoint();
    var actionDescriptor = endpoint.Metadata.GetMetadata<ControllerActionDescriptor>();
    ... 
}

As others have mentioned, injecting IHttpContextAccessor is another way to access HttpContext.

Comments

7

You can inject an IHttpContextAccessor into your AuthorizationHandlers constructor.

e.g.

public class MyAuthorizationHandler : AuthorizationHandler<MyRequirement>
{
    private IHttpContextAccessor _contextAccessor;

    public MyAuthorizationHandler (IHttpContextAccessor contextAccessor)
    {
        _contextAccessor = contextAccessor;
    }

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

        var httpContext = _contextAccessor.HttpContext;
        // do things
    }
}

Comments

2

If it is an MVC context you can access HttpContext, RouteData and everything else MVC provides like this from AuthorizationContext context:

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

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

https://jakeydocs.readthedocs.io/en/latest/security/authorization/policies.html#accessing-mvc-request-context-in-handlers

In .NET 5 you can use this code:

if(context.Resource.GetType().FullName == "Microsoft.AspNetCore.Http.DefaultHttpContext")
{
    var httpContext = context.Resource as Microsoft.AspNetCore.Http.DefaultHttpContext;

}

Comments

1

Without injecting, simple solution!

protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, MyRequirement requirement)
        {
                var authFilterCtx = (Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext)context.Resource;
                var httpContext = authFilterCtx.HttpContext;  
        }

2 Comments

It didn't work for me. System.InvalidCastException: 'Unable to cast object of type 'Microsoft.AspNetCore.Routing.RouteEndpoint' to type 'Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext'.'
have you found a valid solution for netcoreapp3.0?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.