This article shows how to implement a custom ASP.NET Core policy using the AuthorizationHandler class. The handler validates, that the identity from the HttpContext has the authorization to update the object in the database.
Code: https://github.com/damienbod/AspNetCoreAngularSignalRSecurity
History
2023-01-08 Updated Angular 15, .NET 7
2021-01-25 Updated Angular 11.1.0 .NET 5, ngrx implementation
2020-03-21 updated packages, fixed Admin UI STS
2019-08-18 Updated ASP.NET Core 3.0, Angular 8.2.2
2019-02-06 Updated Angular 7.2.4, latest NGRX, SignalR CORS fix
2018-12-12 Updated .NET Core 2.2, ASP.NET Core SignalR 1.1.0, Angular 7.1.3
2018-05-31 Updated Microsoft.AspNetCore.SignalR 2.1
2018-05-08 Updated Microsoft.AspNetCore.SignalR 2.1 rc1, Angular 6
2018-03-15 Updated signalr Microsoft.AspNetCore.SignalR 1.0.0-preview1-final, Angular 5.2.8, @aspnet/signalr 1.0.0-preview1-update1
Scenerio
In the example, each admin user of the client application, can create DataEventRecord entities which can only be accessed by the corresponding identity. If a different identity with a different user sends a PUT request to update the object, a 401 response is returned. Because the Username from the identity is saved in the database for each entity, the custom policy can validate the identity and the entity to be updated.
Creating the Requirement for the Policy
A simple requirement is created for the policy implementation. The AuthorizationHandler implementation requires this and the requirement class is also used to add the policy to the application.
using Microsoft.AspNetCore.Authorization;
namespace ApiServer.Policies;
public class CorrectUserRequirement : IAuthorizationRequirement{}
Creating the custom Handler for the Policy
If a method is called, which is protected by the CorrectUserHandler, the HandleRequirementAsync is executed. In this method, the id of the object to be updated is extracted from the url path. The id is then used to select the Username from the database, which is then compared to the Username from the HttpContext identity name. If the values are not equal, no success message is returned.
using ApiServer.Repositories;
using Microsoft.AspNetCore.Authorization;
using System;
using System.Threading.Tasks;
namespace ApiServer.Policies;
public class CorrectUserHandler : AuthorizationHandler<CorrectUserRequirement>
{
private readonly IDataEventRecordRepository _dataEventRecordRepository;
public CorrectUserHandler(IDataEventRecordRepository dataEventRecordRepository)
{
_dataEventRecordRepository = dataEventRecordRepository;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CorrectUserRequirement requirement)
{
if (context == null) throw new ArgumentNullException(nameof(context));
if (requirement == null) throw new ArgumentNullException(nameof(requirement));
var authFilterCtx = (Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext)context.Resource;
var httpContext = authFilterCtx.HttpContext; var pathData = httpContext.Request.Path.Value.Split("/");
long id = long.Parse(pathData[pathData.Length -1]);
var username = _dataEventRecordRepository.GetUsername(id);
if (username == httpContext.User.Identity.Name)
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
Adding the policy to the application
The custom policy is added to the ASP.NET Core application using the AddAuthorization extension using the requirement.
builder.Services.AddAuthorization( options =>
{
// ...
options.AddPolicy("correctUser",
policyCorrectUser => { policyCorrectUser.Requirements.Add(new CorrectUserRequirement()); });
});
Using the policy in the ASP.NET Core controller
The PUT method uses the correctUser policy to authorize the request.
[Authorize("dataEventRecordsAdmin")]
[Authorize("correctUser")]
[HttpPut("{id}")]
public IActionResult Put(long id, [FromBody]DataEventRecordDto dataEventRecordDto)
{
_dataEventRecordRepository.Put(id, dataEventRecordDto);
return NoContent();
}
If a user logs in, and tries to update an entity belonging to a different user, the request is rejected.

If a user logs in, and tries to update an entity belonging to a different user, the request is rejected.
Links:
https://docs.microsoft.com/en-us/aspnet/core/security/authorization/policies
[…] Implementing custom policies in ASP.NET Core using the HttpContext – Damien Bowden […]
[…] Implementing custom policies in ASP.NET Core using the HttpContext (Damien Bowden) […]
[…] L’implémentation de Custom Policies dans ASP.NET Core en utilisant HttpContext. […]
Don’t forget that it’s diferent on asp.net core 2.0
https://docs.microsoft.com/en-us/aspnet/core/migration/1x-to-2x/identity-2x
Hi Cristovao
This is for ASP.NET Core 2.0
Greetings Damien
Thanks for posting this. I just went through it and wanted to point out that you are missing this line in the Startup class:
services.AddSingleton();
Also, you duplicated a line in your CorrectUserRequirement class.
Woops. IAuthorizationHandler, CorrectUserHandler should be in that AddSingleton.
services.AddSingleton < IAuthorizationHandler, CorrectUserHandler > ();
thanks, will fix it
greetings Damien
As said Wei,
It does not work until you would add:
services.AddSingleton ();