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:
- Policy-based Authorization in ASP.NET Core – A Deep Dive
- Claim type and claim value in claims policy based authorization in asp net core
- 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.