Security authorization
ASP.NET Core C# Dependency Injection OAuth Visual Studio Web API

How to use an Imperative Authorization Policy to Secure Web API Application Resources

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.

Social media & sharing icons powered by UltimatelySocial