Welcome to today’s post.
I will discuss how we can use imperative authorization policy to secure your Web API applications.
The definition is given in a post here:
https://docs.microsoft.com/en-us/archive/msdn-magazine/2017/october/cutting-edge-policy-based-authorization-in-asp-net-core
Declarative authorization allows authorization of resources to be checked before a controller action method is accessed. The implementation of the authorization rule can be built around policies and requirements, which when satisfied, allow access to the resource
Imperative authorization allows authorization of resources to be embedded as code within the logic of controllers or views to allow more fine-grained access to the controller resource. With imperative authorization we can use the IAuthorizationService and execute a custom authorization method.
Authorization policies consist of one or many requirements. The requirements can consist of CRUD requirements, or rule-based requirements, such as user age-based, or financial based restriction.
Let us look at an example of imperative policy-based authorization.
Setting up your application for authorization
In addition to using the
using Microsoft.AspNetCore.Authorization;
namespace, the following is required to use authorization handlers within the .NET Core application.
In the ConfigureServices() method in Startup.cs, setup authorization for your services collection as follows:
public void ConfigureServices(IServiceCollection services)
{
…
services.AddAuthorization(options =>
{
options.AddPolicy("BookLoanAccess", policy =>
{
policy.AddRequirements(
BookLoanOperations.Loan);
});
});
…
}
And configure the handler as shown:
services.AddSingleton<IAuthorizationHandler,
BookLoanAccessHandler>();
In the Configure() method setup authorization for your application as follows:
public void Configure(IApplicationBuilder app,
IHostingEnvironment env)
{
..
app.UseAuthentication();
..
}
Imperative authorization based on policies and requirements
In this example we can allow any user that is authenticated to view books based on custom security criteria.
Before we can use imperative authorization, we need to register IAuthorizationService using dependency injection:
public class LoanController : Controller
{
private readonly ApplicationDbContext _context;
private readonly IAuthorizationService _authorizationService;
ILoanService _loanService;
IBookService _bookService;
IReportService _reportService;
public LoanController(ApplicationDbContext context,
IAuthorizationService authorizationService,
IBookService bookService,
ILoanService loanService,
IReportService reportService)
{
_context = context;
_authorizationService = authorizationService;
_bookService = bookService;
_loanService = loanService;
_reportService = reportService;
}
And implement an authorization handler:
public class BookLoanAccessHandler : AuthorizationHandler<BookLoanRequirement, ReportService>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, BookLoanRequirement requirement, ReportService resource)
{
Task<bool> anyOverdueLoansResult = resource.CurrentUserAnyOverdueLoans();
bool anyOverdueLoans = anyOverdueLoansResult.GetAwaiter().GetResult();
if (!anyOverdueLoans)
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
namespace BookLoan.Authorization
{
public class BookLoanRequirement: IAuthorizationRequirement
{
public BookLoanRequirement()
{
}
}
}
Where ReportService is a service or table that stores or returns additional attributes or results for our handler to interpret.
The controller can be implemented as follows:
We implement controller authorization within the code block using the authorization service as shown:
// GET: LoanViewModels/Create
public async Task<IActionResult> Create(int id)
{
// use imperative authorization to check no outstanding overdue loans.
if ((await _authorizationService
.AuthorizeAsync(User, _reportService, new BookLoanRequirement())).Succeeded)
{
LoanViewModel lvm = _loanService.CreateNewBookLoan(id);
lvm.LoanedBy = User.Identity.Name;
BookLoan.Views.Loan.CreateModel createModel = new CreateModel(_context);
createModel.LoanViewModel = lvm;
return View(createModel);
}
else
{
return new ChallengeResult();
}
}
I hope this has been a useful post on how to secure your controllers using imperative policy based authorizations.
In a future post I will show how to apply both imperative and declarative based authorizations to secure your controllers and views.

Andrew Halil is a blogger, author and software developer with expertise of many areas in the information technology industry including full-stack web and native cloud based development, test driven development and Devops.