Search code examples
asp.netwindows-authenticationasp.net-core-3.0

How are ASP.NET Roles used with Authorization?


I'm using ASP.NET Core and hosting what is basically the default template with Windows Authentication enabled. I'm hosting this on a dedicated IIS server, and have verified the app is receiving correct information from AD and it correctly authenticates my session.

I feel like I'm trying to do something very simple. If the user is in the security group (from AD) "Admin" they are able to access a specific function. If they aren't in that group they do not get access.

I slapped on the [Authorize] attribute to the service

(in ConfigureServices)
services.AddAuthentication(IISDefaults.AuthenticationScheme);
(in Configure)
app.UseAuthorization();

(in service)
[Authorize]
public class SiteService
    {
        private readonly string _route;
        private readonly HttpClient _httpClient;

        public SiteService(HttpClient httpClient)
        {
            _httpClient = httpClient;
            _route = httpClient.BaseAddress.AbsoluteUri;
        }

        public async Task<IEnumerable<Site>> GetSites()
        {

        }
   }

I can see in the logs that accessing the service gives me Domain/User. I then looked up the MS Docs here: https://learn.microsoft.com/en-us/aspnet/core/security/authorization/roles?view=aspnetcore-3.1

And slapped on [Authorize(Roles = "Admin"). That worked. I then switched "Admin" with "sldkfjslksdlfkj". Nothing changed...I can still access the service.

Why is the Roles="x" check not working? How can I enable a relatively simple check to AD for a Security Group?


Solution

  • You could write a custom Policy Authorization handlers to check all of the users' ADGroups and check if they contain the desired group name.

    Refer to the following:

    1.Create CheckADGroupRequirement(accept a parameter)

        public class CheckADGroupRequirement : IAuthorizationRequirement
        {
            public string GroupName { get; private set; }
    
            public CheckADGroupRequirement(string groupName)
            {
                GroupName = groupName;
            }
        }
    

    2.Create CheckADGroupHandler

        public class CheckADGroupHandler : AuthorizationHandler<CheckADGroupRequirement>
        {
            protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
                                                           CheckADGroupRequirement requirement)
            {
                //var isAuthorized = context.User.IsInRole(requirement.GroupName);
    
                var groups = new List<string>();//save all your groups' name
                var wi = (WindowsIdentity)context.User.Identity;
                if (wi.Groups != null)
                {
                    foreach (var group in wi.Groups)
                    {
                        try
                        {
                            groups.Add(group.Translate(typeof(NTAccount)).ToString());
                        }
                        catch (Exception e)
                        {
                            // ignored
                        }
                    }
                   if(groups.Contains(requirement.GroupName))//do the check
                    {
                        context.Succeed(requirement);
                    }
                }
    
                return Task.CompletedTask;
            }
        }
    

    3.Register Handler in ConfigureServices

        services.AddAuthorization(options =>
        {
            options.AddPolicy("AdminOnly", policy =>
                policy.Requirements.Add(new CheckADGroupRequirement("DOMAIN\\Domain Admin")));//set your desired group name
                //other policies
        });
    
        services.AddSingleton<IAuthorizationHandler, CheckADGroupHandler>();
    

    4.Use on controller/service

        [Authorize(Policy = "AdminOnly")]
        public class SiteService