Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Suggestion] Add some instructions for getting role claims. #32512

Open
travaille-dev opened this issue May 3, 2024 · 4 comments
Open

[Suggestion] Add some instructions for getting role claims. #32512

travaille-dev opened this issue May 3, 2024 · 4 comments
Assignees

Comments

@travaille-dev
Copy link

Description

I ran into a use case where I wanted to not only validate that a user can sign in, but that they are in a particular role before viewing a page/component.

I had made a ticket here dotnet/aspnetcore#55314 and I thought it might be useful for others to have this documented. It could be helpful for other providers as well if they have something like multiple policies you'd like to map or another claim type with multiple values.

I am using Entra as my oidc provider, so the prerequisites for this are having an entra app and app registration in order to assign users/groups/apps to role(s).

A user can be assigned to multiple roles so I needed to adjust the UserInfo Class at https://github.com/dotnet/blazor-samples/blob/main/8.0/BlazorWebAppOidc/BlazorWebAppOidc.Client/UserInfo.cs to the following

using System.Security.Claims;

namespace BlazorWebAppOidc.Client;

// Add properties to this class and update the server and client AuthenticationStateProviders
// to expose more information about the authenticated user to the client.
public sealed class UserInfo
{
    public required string UserId { get; init; }
    public required string Name { get; init; }
    public required string[] Roles { get; init; }

    public const string UserIdClaimType = "sub";
    public const string NameClaimType = "name";
    private const string RoleClaimType = "roles";

    public static UserInfo FromClaimsPrincipal(ClaimsPrincipal principal) =>
        new()
        {
            UserId = GetRequiredClaim(principal, UserIdClaimType),
            Name = GetRequiredClaim(principal, NameClaimType),
            Roles = principal.FindAll(RoleClaimType).Select(c => c.Value).ToArray(),
        };

    public ClaimsPrincipal ToClaimsPrincipal() =>
        new(new ClaimsIdentity(
            Roles.Select(role => new Claim(RoleClaimType, role))
                .Concat(new[]
                {
                    new Claim(CustomClaimType, UserId),
                    new Claim(NameClaimType, Name)
                }),
            authenticationType: nameof(UserInfo),
            nameType: NameClaimType,
            roleType: RoleClaimType));

    private static string GetRequiredClaim(ClaimsPrincipal principal, string claimType) =>
        principal.FindFirst(claimType)?.Value ?? throw new InvalidOperationException($"Could not find required '{claimType}' claim.");
}

Also the Entra string claim for the role claim is actually "roles" so you need to change the string value in https://github.com/dotnet/blazor-samples/blob/main/8.0/BlazorWebAppOidc/BlazorWebAppOidc/Program.cs
This portion was elusive for me and seems silly now, but I imagine different providers can have different naming. When I was using just microsoft identity nuget packages the roles actually came through as appRole 🤷‍♀️

oidcOptions.TokenValidationParameters.RoleClaimType = "roles";

Finally, in your UserClaims page component you can add the following in order to test out your roles

@attribute [Authorize(Roles = "Role1")]

<PageTitle>User Claims</PageTitle>
<AuthorizeView Roles="Role2">
    <Authorized>
        You have Role2
    </Authorized>
    <NotAuthorized>
        You do not have Role2
    </NotAuthorized>
</AuthorizeView>

Page URL

https://learn.microsoft.com/en-us/aspnet/core/blazor/security/blazor-web-app-with-oidc?view=aspnetcore-8.0&pivots=with-bff-pattern#configuration-1

Content source URL

https://github.com/dotnet/AspNetCore.Docs/blob/main/aspnetcore/blazor/security/blazor-web-app-with-oidc.md

Document ID

c3346d3a-346b-8db4-2650-ec044b3f0dd9

Article author

@guardrex

Copy link
Contributor

github-actions bot commented May 3, 2024

🕺💃 Happy Cinco de Mayo! 🥳🎈

A green dinosaur 🦖 will be along shortly to assist. Stand-by ........

@guardrex
Copy link
Collaborator

guardrex commented May 3, 2024

Thanks @travaille-dev ... Yes, I believe this would be a great addition to the BWA article. It will take a few weeks (or months 🙈) due to a heavy workload at the moment, but I'll get back to it as soon as I can 🏃‍♂️.

@travaille-dev
Copy link
Author

All good here! I think this actual sample isn't even slated to be 'available' for folks until November, so we can close this if it's something already on the todo list.

@guardrex
Copy link
Collaborator

guardrex commented May 6, 2024

Just confirming ... it will take a little while to reach this. I have a large tutorial to write on my plate 🍽️, which will take quite a bit of time in the near-term to digest. This won't get lost ... it's on the menu 📖. (I must be hungry 🍗 ... there are a lot of food references in this comment! 🤣

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: P2 - Medium Priority
Development

No branches or pull requests

3 participants