I am trying to set up AAD Authorization based on user defined roles following this doc https://learn.microsoft.com/en-us/aspnet/core/blazor/security/webassembly/azure-active-directory-groups-and-roles?view=aspnetcore-3.1#user-defined-roles I am able to set it up in the app manifest and get the API authorization working. However when I try to do it on the UI side I cannot get the claim to appear. I did the json interpreting classes (DirectoryObjects, CustomUserAccount and Value(used by directory object)). I also added the CustomUserFactory removing the group stuff since I only care about roles:
private readonly ILogger<CustomUserFactory> _logger;
private readonly IHttpClientFactory _clientFactory;
public CustomUserFactory(IAccessTokenProviderAccessor accessor,
IHttpClientFactory clientFactory,
ILogger<CustomUserFactory> logger)
: base(accessor)
{
_clientFactory = clientFactory;
_logger = logger;
}
public async override ValueTask<ClaimsPrincipal> CreateUserAsync(
CustomUserAccount account,
RemoteAuthenticationUserOptions options)
{
var initialUser = await base.CreateUserAsync(account, options);
if (initialUser.Identity.IsAuthenticated)
{
var userIdentity = (ClaimsIdentity)initialUser.Identity;
foreach (var role in account.Roles)
{
userIdentity.AddClaim(new Claim("role", role));
}
}
return initialUser;
}
and then I modified the program.cs as the doc mentioned:
builder.Services.AddMsalAuthentication<RemoteAuthenticationState,
CustomUserAccount>(options =>
{
builder.Configuration.Bind("AzureAd", options.ProviderOptions.Authentication);
options.ProviderOptions.DefaultAccessTokenScopes.Add("apiaccessguid");
options.UserOptions.RoleClaim = "role";
}).AddAccountClaimsPrincipalFactory<RemoteAuthenticationState, CustomUserAccount,
CustomUserFactory>();
when that didn't work I tried adding it as a policy with no luck as well:
builder.Services.AddAuthorizationCore(options =>
{
options.AddPolicy("Admin", policy =>
policy.RequireClaim("role", "admin"));
});
for restricting the view I tried in code with the user.IsInRole("admin")
and in the UI with
<AuthorizeView Roles="admin">
<li class="nav-item px-3">
<NavLink class="nav-link" href="Admin">
Admin
</NavLink>
</li>
</AuthorizeView>
and with policy:
<AuthorizeView Policy="Admin">
<Authorized>
<p>
The user is in the 'Administrator' AAD Administrative Role
and can see this content.
</p>
</Authorized>
<NotAuthorized>
<p>
The user is NOT in the 'Administrator' role and sees this
content.
</p>
</NotAuthorized>
</AuthorizeView>
and none of them worked. Is there something I am missing? I also verified that the token has the admin role.
I got it working by using RequireRole in the policy options.
For example, I added the app role to the manifest:
"appRoles": [
{
"allowedMemberTypes": [
"User"
],
"description": "Reader role.",
"displayName": "Reader",
"id": "41d9ba42-456e-4471-8946-24216e5f6c64",
"isEnabled": true,
"lang": null,
"origin": "Application",
"value": "Reader"
}
]
Configure the policy via RequireRole:
builder.Services.AddAuthorizationCore(options =>
{
options.AddPolicy("app-reader", policy => policy.RequireRole("Reader"));
});
And then use as per:
<AuthorizeView Policy="app-reader">
<Authorized>
<p>
The user is in the 'Reader' Role
and can see this content.
</p>
</Authorized>
<NotAuthorized>
<p>
The user is NOT in the 'Reader' role
and sees this content.
</p>
</NotAuthorized>
</AuthorizeView>
Or, as an attribute on a razor page:
@attribute [Authorize(Policy = "app-reader")]
Found my problem, the code was fine, the problem was on the Azure registration side, The client uses the roles registered in the client app in Azure while the server uses the ones in the server app. so make sure you register the user in both with the same role.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With