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
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
{
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()
.
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
{
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
.