How can I retrieve all the local groups for a domain user in C# in .NET Core 3.1?

Viewed 172

I have a web app (built in C# with .NET Core 3.1) and I need to retrieve a user's local group membership on the web server where the app runs. The users are domain users and not local ones on that machine and have to provide their domain credentials when they log into the app. The code I'm having trouble with is as follows:

var machineContext  = new PrincipalContext(ContextType.Machine, Environment.GetEnvironmentVariable("COMPUTERNAME"));
var userPrincipal = UserPrincipal.FindByIdentity(machineContext, userName);

userName is built up using .NET Core's IHttpContextAccessor and works perfectly. I left that code out for brevity. Using that code to try to build a PrincipalContext for the machine, userPrincipal is always null. I've been able to get this to sort of work as an alternative:

var pc = new PrincipalContext(System.DirectoryServices.AccountManagement.ContextType.Domain, Environment.UserDomainName);
var p = UserPrincipal.FindByIdentity(pc, userName);
var upn = p.UserPrincipalName;

var currWinIdentity = new System.Security.Principal.WindowsIdentity(upn);
currWinIdentity.Groups.ToList()
    .ForEach(h =>
    {
        var groupName = h.Translate(typeof(System.Security.Principal.NTAccount));
        Console.WriteLine($"{groupName} ({h.Value})");
    });

I found that building a WindowsIdentity using the user's UPN gets me to a superset of the list of groups I want with the above code. The problem is that to get this to work -- presumably this is because the PrincipalContext I'm building is built as ContextType.Domain but that was the only way I could get it to work -- I have to set the app pool in IIS to run as a user that's on the domain, instead of running as the default ApplicationPoolIdentity and for some of the client environments I'm going to put this on, that's not going to work.

So, does anyone know how I can fix my code to behave the way I want or is there a better way to get the local groups for a domain user?

1 Answers

Here is what worked for me on a WebAPI project using Windows Authentication (.net core 2.1)

[HttpGet]

public ActionResult<IEnumerable<string>> Get()
    {
        var username = HttpContext.User.Claims.FirstOrDefault(p => p.Type == ClaimTypes.Name)?.Value;
        var claims = HttpContext.User.Identity;
        var wi = (WindowsIdentity)claims;

        List<String> groupVals = new List<String>();

        foreach(var group in wi.Groups)
        {

            var gn = group.Translate(typeof(NTAccount)).ToString();
            groupVals.Add(gn);
        }
    
        return new string[] { "value1", "value2" };
    }
Related