Note: Need to configure both .Client and .Server projects.
.Client
Create a new class called CustomUserFactory.cs
using System.Linq;
using System.Security.Claims;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication.Internal;
namespace Models
{
public class CustomUserFactory
: AccountClaimsPrincipalFactory<RemoteUserAccount>
{
public CustomUserFactory(IAccessTokenProviderAccessor accessor)
: base(accessor)
{
}
public async override ValueTask<ClaimsPrincipal> CreateUserAsync(
RemoteUserAccount account,
RemoteAuthenticationUserOptions options)
{
var user = await base.CreateUserAsync(account, options);
if (user.Identity.IsAuthenticated)
{
var identity = (ClaimsIdentity)user.Identity;
var roleClaims = identity.FindAll(identity.RoleClaimType).ToArray();
if (roleClaims != null && roleClaims.Any())
{
foreach (var existingClaim in roleClaims)
{
identity.RemoveClaim(existingClaim);
}
var rolesElem = account.AdditionalProperties[identity.RoleClaimType];
if (rolesElem is JsonElement roles)
{
if (roles.ValueKind == JsonValueKind.Array)
{
foreach (var role in roles.EnumerateArray())
{
identity.AddClaim(new Claim(options.RoleClaim, role.GetString()));
}
}
else
{
identity.AddClaim(new Claim(options.RoleClaim, roles.GetString()));
}
}
}
}
return user;
}
}
}
Add to Main of Program.cs (Client)
// Custom Identity Roles
builder.Services.AddApiAuthorization()
.AddAccountClaimsPrincipalFactory<CustomUserFactory>();
.Server
Add to ConfigureServices of Startup.cs (Server)
services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddRoles<IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddIdentityServer()
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>(options => {
options.IdentityResources["openid"].UserClaims.Add("role");
options.ApiResources.Single().UserClaims.Add("role");
});
Result
Index.razor (Client)
<AuthorizeView>
<Authorized>
<p>Name: @context.User.Identity.Name</p>
<p>Claims: @context.User.Claims.Count().ToString()</p>
<p>IsInRole POSUser: @context.User.IsInRole("OrgAdmin")</p>
@foreach (var claim in context.User.Claims)
{
<dt title="@claim.Type">@claim.Type</dt>
<dd>@claim.Value</dd>
}
</Authorized>
</AuthorizeView>
OrgAdminOnly.razor (Client)
@attribute [Authorize(Roles = "SiteAdmin,OrgAdmin")]
Comments