Resource-based authorization with polymorphic UserId model (ASP.NET Core, EF Core)
I added resource-based authorization to my ASP.NET Core project today; the approach that I used was to add a property UserId to an abstract entity class and then a requirement handler class that takes that type as the resource parameter to compare the current user’s ID to. It’s not groundbreaking at all, but it is another example of resource-based authorization in ASP.NET Core which I personally find the API to be somewhat confusing in design to use, and overall the approach builds on my previous example of resource-based authorization in ASP.NET Core.
With this, authorization will be possible for entity classes derived from this:
In order to add the column to the database and then make it non-nullable, the above would have public required string? UserId { get; set; } instead for the first migration, and after it is ensured that all records in the database across the relevant tables have a non-null UserId, the not null constraint can be added. The required ensures that all constructors of a descended EntityBase will set the UserId during that time between migrations (for a small non-enterprise app with no traffic in a staging environment like this).
To implement resource-based authorization, both a requirement and handler are needed:
I realized that a string value is needed in two places so I put this in the requirement class as a static property (otherwise that class is just empty).
Then in Program.cs I changed this:
to this:
It is necessary to register the handler for dependency injection with AddSingleton:
Here is the class which has the IAuthorizationHandler injected into it:
Above is also the second place that string that was made a static property of the requirement handler class needs to be used. It is also where unit tests that mock the IAuthorizationService would pass while the app throws a runtime exception if you forgot to register the requirement handler for dependency injection in Program.cs (learned the hard way).