Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading the AuthorizationFilterContext in netcore api 3.1

Tags:

I have a working netcore 2.2 project where I have implemented a custom policy that checks for API Keys.

In the startup.cs I am adding this policy like this

//Add Key Policy services.AddAuthorization(options => {     options.AddPolicy("AppKey", policy => policy.Requirements.Add(new AppKeyRequirement())); }); 

In my AppKeyRequirement I inherit from AuthorizationHandler and resolve the keys in the incoming requests like this

protected override Task HandleRequirementAsync(AuthorizationHandlerContext authContext, AppKeyRequirement requirement) {     var authorizationFilterContext = (AuthorizationFilterContext)authContext.Resource;     var query = authorizationFilterContext.HttpContext.Request.Query;      if (query.ContainsKey("key") && query.ContainsKey("app"))     { // Do stuff 

This does not work in netcore 3.1

I am getting the following error:

Unable to cast object of type 'Microsoft.AspNetCore.Routing.RouteEndpoint' to type 'Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext'.

What is the correct way to do this in core 3 and above ?

As pointed out by Kirk Larkin, the correct way in .net 3.0 and above is to inject IHttpContextAccessor into the Auth handler and use that.

My question at this point is how do I inject this ? I cant pass this in startup.cs or at least I am not seeing how.

Any ideas/hints will be much appreciated.

like image 312
w2olves Avatar asked Oct 25 '19 20:10

w2olves


People also ask

How do I access HttpContext in Web API?

If you absolutely must do this, you can grab the HTTP context like so: var context = Request. Properties["MS_HttpContext"] as HttpContext; At which point you just use its Session property to get the session.

How do I get HttpContext in .NET core?

ASP.NET Core apps access HttpContext through the IHttpContextAccessor interface and its default implementation HttpContextAccessor. It's only necessary to use IHttpContextAccessor when you need access to the HttpContext inside a service.

How use HttpContext current in .NET core?

Current property, instead it is available in the HttpContext class in ASP.Net Core applications. Session can be enabled using the Configure method. Inside this method, you will have to call the UseSession method of the app object. Note: It is mandatory to call the UseSession method before the UseMvc method.

What is the use of IHttpContextAccessor?

The IHttpContextAccessor is an interface for . Net Core for accessing HttpContext property. This interface needs to be injected as dependency in the Controller and then later used throughout the Controller.


1 Answers

ASP.NET Core 5.x

Based on the announcement for ASP.NET Core 5.0-preview7 onwards, the Resource property is set to the current HttpContext for the request (when using endpoint routing). This means the following example will work for ASP.NET Core 5.0 onwards, without the need for IHttpContextAccessor:

public class AppKeyAuthorizationHandler : AuthorizationHandler<AppKeyRequirement> {     protected override Task HandleRequirementAsync(         AuthorizationHandlerContext authContext, AppKeyRequirement requirement)     {         var httpContext = authContext.Resource as HttpContext;         var query = httpContext.Request.Query;          if (query.ContainsKey("key") && query.ContainsKey("app"))         {             // ...         }     } } 

The RouteEndpoint is still available, using httpContext.GetEndpoint().

ASP.NET Core 3.x

In versions prior to ASP.NET Core 3.0, implementations of IAuthorizationHandler were called during the MVC pipeline. In 3.0 onwards, which uses endpoint-routing (by default), these implementations are called by the authorization middleware (UseAuthorization()). This middleware runs before the MVC pipeline, rather than as part of it.

This change means that AuthorizationFilterContext is no longer passed in to authorization handlers. Instead, it's an instance of RouteEndpoint, which doesn't provide access to the HttpContext.

In your example, you're only using AuthorizationFilterContext to get hold of HttpContext. In 3.0+, inject IHttpContextAccessor into your authorization handler and use that. Here's an example for completeness:

public class AppKeyAuthorizationHandler : AuthorizationHandler<AppKeyRequirement> {     private readonly IHttpContextAccessor httpContextAccessor;      public AppKeyAuthorizationHandler(IHttpContextAccessor httpContextAccessor)     {         this.httpContextAccessor = httpContextAccessor;     }      protected override Task HandleRequirementAsync(         AuthorizationHandlerContext authContext, AppKeyRequirement requirement)     {         var httpContext = httpContextAccessor.HttpContext;         var query = httpContext.Request.Query;          if (query.ContainsKey("key") && query.ContainsKey("app"))         {             // ...         }     } } 

You might also need to register IHttpContextAccessor in ConfigureServices:

services.AddHttpContextAccessor(); 

See Use HttpContext from custom components for more information about using IHttpContextAccessor.

like image 191
Kirk Larkin Avatar answered Oct 04 '22 22:10

Kirk Larkin