Search code examples
c#asp.netauthenticationblazorauthorization

<AuthorizeView> not recognizing role claim


I have a Blazor Server app that uses Windows Auth. Based on the group memberships of the user, I am adding role claims using IClaimsTransformation. The group-to-role mapping is fetched from a DB.

This is my implementation of IClaimsTransformation:

public class WindowsAuthClaimsTransformation : IClaimsTransformation
{
    private readonly IDataService _dataService;
    public WindowsAuthClaimsTransformation(IDataService dataService)
    {
        _dataService = dataService;
    }
    public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
    {
        if (!(principal.Identity is ClaimsIdentity))
            return principal;

        var identity = principal.Identity as ClaimsIdentity;

        if (identity?.IsAuthenticated == false)
            return principal;

        var userGroupClaims = identity.FindAll("http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid").ToList();

        var groupRoleMappings = await _dataService.GetList<GroupRoleMapping>();

        var roles = new List<string>();

        foreach (var mapping in groupRoleMappings)
        {
            if (userGroupClaims.Any(x => x.Value.TrimEnd() == mapping.GroupSID))
            {
                roles.Add(mapping.RoleName);
            }
        }

        foreach (var role in roles)
        {
            identity.AddClaim(new Claim(ClaimTypes.Role, role));
        }

        return principal;
    }
}

This is registered as a scoped service in Program.cs:

    public class Program
    {
        public static void Main(string[] args)
        {
                var builder = WebApplication.CreateBuilder(args);

                builder.Services.AddRazorComponents()
                    .AddInteractiveServerComponents();

                // add windows auth
                builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
                    .AddNegotiate();

                // database interaction logic
                builder.Services.AddScoped<IDataService, SqlDataService>();

                // add claimstransformation
                builder.Services.AddScoped<IClaimsTransformation, WindowsAuthClaimsTransformation>();

                builder.Services.AddAuthorization(options =>
                {
                    // By default, all incoming requests will be authorized according to the default policy.
                    options.FallbackPolicy = options.DefaultPolicy;
                });

                var app = builder.Build();
               
                // Configure the HTTP request pipeline.
                if (!app.Environment.IsDevelopment())
                {
                    app.UseExceptionHandler("/Error");

                    app.UseHsts();
                }

                app.UseHttpsRedirection();

                app.UseStaticFiles();
                app.UseAntiforgery();

                app.MapRazorComponents<App>()
                    .AddInteractiveServerRenderMode();

                app.Run();
        }
    }

SamplePage.razor:

<AuthorizeView Roles="Admin" >
    <Authorized>
            <p>You are an admin. Your roles: @string.Join(", ", @context.User.Claims.Where(c => c.Type == ClaimTypes.Role).Select(c => c.Value))</p>
            <br />
    </Authorized>
    <NotAuthorized>
            <p>You are not an admin. Your roles: @string.Join(", ", @context.User.Claims.Where(c => c.Type == ClaimTypes.Role).Select(c => c.Value))</p>
    </NotAuthorized>
</AuthorizeView>

This gives me the following text output:

You are not an admin. Your roles: Admin, User

Which makes me think that my ClaimsTransformation is working properly, however the AuthorizeView is not properly recognizing it. How can I solve this?


Solution

  • It could pass the authorization if you add the role claims like below:

    foreach (var role in roles)
    {
        identity.AddClaim(new Claim(identity.RoleClaimType, role));
        //identity.AddClaim(new Claim(ClaimTypes.Role, role));
    }