(28/30) Learning Blazor Together: Policy-based Authorization

(28/30) Learning Blazor Together: Policy-based Authorization

It was mentioned earlier that `ASP.NET Core Identity` uses `Claim`-based authentication. In fact, `ASP.NET Core Identity` has different types of authorization methods, the simplest being `Login Authorization`, `Role Authorization`, and `Claim Authorization`. However, all of the above are implemented in one way: Policy-based Authorization.

Last updated 12/25/2021 5:51 PM
StrayaWorker
4 min read
Category
Blazor
Topic
Learning Blazor Together Series
Tags
.NET C# ASP.NET Core Blazor Authentication

Previously, we mentioned that ASP.NET Core Identity uses Claim-based authentication. In fact, ASP.NET Core Identity supports different types of authorization methods: the simplest being login authorization, role authorization, and claim authorization. However, all of these are implemented in one way: policy-based authorization.

The so-called policy-based authorization means customizing a Policy. As long as the conditions defined by the Policy are met, authorization is granted, regardless of whether the condition is the logged-in user, having a certain Role, a certain Claim, or having both a Role and a Claim, etc.

It might be difficult to understand at first. The author also took some time to grasp it. A Claim corresponds to a piece of information like new Claim("Age", "18"), while a policy is equivalent to a rule, such as a bar requiring that customers must be over 18 to enter. As mentioned before, a Role is just a Claim with a type of Role, so the same logic applies.

Defining a Policy in ASP.NET Core is not difficult; it can be done in Program.cs. The code below defines a Policy named "IsAdmin". This Policy requires having the "ManageRole" Claim to pass authorization.

builder.Services.AddAuthorization(options =>
{
	options.AddPolicy("IsAdmin", policy => { policy.RequireClaim("ManageRole"); });
});

Next, go to the page for editing user Claims and make the currently logged-in user test@gmail.com hold all Claims; otherwise, these pages won't be visible after applying the policy. Also, edit user@gmail.com but save without selecting any Claims, to facilitate testing later.

When applying, it's the same as with Roles: just add the Policy parameter to the [AuthorizeAttribute]. Take UserManagement.razor as an example.

@page "/UserManagement/UserList" @attribute [Authorize(Policy = "IsAdmin")] …

NavMenu.razor also creates a new <AuthorizeView> Component, using the Policy variable.

<AuthorizeView Policy="IsAdmin">
  <Authorized>
    <li class="nav-item px-3">
      <NavLink
        class="nav-link"
        href="UserManagement/UserList"
        Match="NavLinkMatch.All"
      >
        <span class="bi bi-people h4 p-2 mb-0" aria-hidden="true"></span> Users
      </NavLink>
    </li>
  </Authorized>
</AuthorizeView>

However, if you log in as user@gmail.com, you can still see the User management page even though ManageUser is false. This is because the Policy "IsAdmin" only requires the "ManageRole" ClaimType. Usually, systems do not authorize this way; instead, they compare both ClaimType and ClaimValue. So, improve the Policy "IsAdmin" by specifying that the ClaimValue for "IsAdmin" must be "true". This completes a simple Policy authorization.

Another thing to note: ASP.NET Core handles ClaimType in a case-insensitive manner, but it is case-sensitive for ClaimValue. Using Policy "IsAdmin" as an example, the ClaimType could be "manageUser" or "manageuser", while the ClaimValue must be "true".

References:

  1. Policy-based Authorization in ASP.NET Core – A Deep Dive
  2. Claim type and claim value in claims policy based authorization in asp net core
  3. Simple authorization in ASP.NET Core

Note: The code in this article is refactored using .NET 6 + Visual Studio 2022. You can click the original article link to compare with the refactored code. Thank you for reading and supporting the original author.

Keep Exploring

Related Reading

More Articles
Same category / Same tag 12/25/2021

(29/30)Learn Blazor Together: Blazor Unit Testing

The most boring part of developing a system is probably fixing bugs, especially errors like trying to access a null object (`Object reference not set to an instance of an object.`), which is the most common problem most people encounter when they first step into programming. To break free from the tedious bug-fixing process, this article introduces `unit testing`.

Continue Reading