Asp Net Core 3.1 Authorization by Custom Roles

Steven

I've seen basically the same question answered for net core 2.2 on ASP Net Forum. When I tried to implement for my net core 3.1 application, I'm getting an error

System.InvalidCastException: Unable to cast object of type 'System.Security.Claims.ClaimsIdentity' to type 'System.Security.Principal.WindowsIdentity'

The error happens on the RoleAuthHandler.cs trying to cast Identity to WindowsIdentity.

I'm wondering if there has been change between core 2.2 and 3.1 that explains this or I'm doing something wrong. Any help would be great.

Startup.cs contains

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();

    services.AddSingleton<IAuthorizationHandler, RoleAuthHandler>();

    services.AddAuthorization(options =>
        options.AddPolicy(
            Role.Admin,
            policy => policy.AddRequirements(new RoleRequirement(Role.Admin))));
}

Role.cs

public static class Role
{
    public const string Guest = "Guest";
    public const string Admin = "Admin";
}

RoleRequirement.cs

public class RoleRequirement : IAuthorizationRequirement
{
    public string[] Roles { get; }

    public RoleRequirement(params string[] roles)
    {
        this.Roles = roles;
    }
}

RoleAuthHandler.cs contains

protected override Task HandleRequirementAsync(
    AuthorizationHandlerContext context,
    RoleRequirement requirement)
{
    var wi = (WindowsIdentity)context.User.Identity;
    var groupSet = new HashSet<string>();

    if (wi.Groups != null)
    {
        foreach (var group in wi.Groups)
        {
            groupSet.Add(group.Translate(typeof(NTAccount)).ToString());
        }
    }

    string[] userRoles = roleService.GetRolesForGroup(groupSet);
    var intersectRoles = Enumerable.Intersect(userRoles, requirement.Roles, StringComparer.OrdinalIgnoreCase);

    if (intersectRoles.Count() > 0)
    {
        context.Succeed(requirement);
    }

    return Task.CompletedTask;
}

Controller class

[Authorize]
[ApiController]
[Route("[controller]")]
public class InterestingController : ControllerBase
{
    [HttpGet]
    public string Get()
    {
        return "Something Interesting";
    }
}
Steven

@Sayah imad - Thanks for the reminder. I had seen this solution on a post somewhere and dismissed it because the information I was looking for was "what group does the user belong to". What I didn't realize was that the information was availabile in the ClaimsIdentity. Your mention, made me think twice about it and I found my answer:

protected override Task HandleRequirementAsync(
        AuthorizationHandlerContext context,
        RoleRequirement requirement)
    {
        var claimsIdentity = (ClaimsIdentity)context?.User.Identity;
        var userGroups = claimsIdentity.Claims
            .Where(x => x.Type.Contains("groupsid", StringComparison.OrdinalIgnoreCase))
            .ToList();

        if (userGroups == null || !userGroups.Any())
        {
            return Task.CompletedTask;
        }

        var groupNames = new HashSet<string>();
        foreach (var group in userGroups)
        {
            var groupName = new SecurityIdentifier(group.Value)
                .Translate(typeof(NTAccount))
                .ToString();
            groupNames.Add(groupName);
        }

        var userRoles = this.authenticationService.GetRoles(groupNames.ToArray());

        // If the user is an Admin, always allow
        if (userRoles.Contains(Role.Admin))
        {
            context.Succeed(requirement);
            return Task.CompletedTask;
        }

        var intersectingRoles = Enumerable.Intersect(
            userRoles,
            requirement?.Roles,
            StringComparer.OrdinalIgnoreCase);
        if (intersectingRoles?.Count() > 0)
        {
            context.Succeed(requirement);
        }

        return Task.CompletedTask;
    }

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

Custom user authorization based with roles in asp.net mvc

Users Roles Permissions using ASP.NET Core Identity 3

How to add custom roles to ASP.NET Core

ASP.NET Core Custom Role Based Authorization (Custom User.IsInRole)?

Dynamic authorization of roles asp.net core

ASP.NET Core Custom Policy Based Authorization - unclear

Asp.Net Core custom authorization always ends with 401 Unauthorized

ASP.NET Core 2 - Identity - DI errors with custom Roles

Custom Bearer Token Authorization for ASP.Net Core

Custom Authorization in Asp.net core 2.1 web api

How to create custom Authorization for ASP.NET MVC5 Web Api With Roles and Permitions for them?

ASP.NET CORE Adding and Removing Roles

.Net Core 3 Custom Authorization Policy - Access to Action Verb

ASP.NET Core Web API and roles authorization

Asp.Net Core Identity - simple Authorization without Roles table

Custom authorization filter not working in ASP.NET Core 3

Authorization failing for custom authentication handler for ASP.NET Core 3.1?

Override authorization policy in ASP.NET Core 3

Individual page authorization based on roles in ASP.NET MVC 5

ASP.NET Core 2.0 Identity update user roles only after re-authorization

custom authorization in asp.net core mvc

Custom Authorization attribute asp.net core

Role Authorization in Asp.Net Core 3 adding roles from class properties

ASP.NET Core authorization not working for nested roles

ASP.Net Core 3.0 merged roles

Custom Authorization attribute doesn't allow authorize in asp.net core 3

ASP.NET Core Custom Authorization & Memory Cache

Asp.net Core MVC Roles and Authorization

Custom authorization in ASP.NET Core with enum roles