0

I've got a WebSite and API hosted on the same server on IIS. In the API (.NET) I need to acquire list of AD Groups that the user that is using the website belongs to. It works locally (Postman calls to API on IIS Express) but it doesn't when ran on our server. Code for acquiring AD Groups is this:

            string[] output = null;
            string username = GetUserName();
            using (var ctx = new PrincipalContext(ContextType.Domain))
            using (var user = UserPrincipal.FindByIdentity(ctx, username))
            {
                if (user != null)
                {
                    output = user.GetGroups() //this returns a collection of principal objects
                        .Select(x => x.SamAccountName) // select the name.  you may change this to choose the display name or whatever you want
                        .ToArray(); // convert to string array
                }
            }

Username is recognized correctly and the same value is passed on localhost and on server, so that's not an issue. Line:

using (var user = UserPrincipal.FindByIdentity(ctx, username))

returns an Exception:

An exception of type 'System.DirectoryServices.DirectoryServicesCOMException' occurred in System.DirectoryServices.AccountManagement.dll but was not handled in user code

It's probably something in IIS settings but I can't figure out what. I tried setting Identity of DefaultAppPool (ApplicationPool that Web and API is assigned to) to NetworkService, but it didn't help.

PRHMN
  • 109
  • 3
  • 13
  • Possible duplicate of [System.DirectoryServices.DirectoryServicesCOMException: An operations error occurred](https://stackoverflow.com/questions/13688031/system-directoryservices-directoryservicescomexception-an-operations-error-occu) – ste-fu Oct 18 '18 at 12:44
  • Tried that, it didn't work. Don't if the fact that I use DefaultAppPool has anythind to do with it, but still. – PRHMN Oct 18 '18 at 12:51

1 Answers1

3

You need to enable Windows Authentication if you haven't already. Instructions are here: https://support.microsoft.com/en-in/help/323176/how-to-implement-windows-authentication-and-authorization-in-asp-net

But the basic idea is that you use this in your web.config:

<system.webServer>
  <security>
    <authentication>
      <windowsAuthentication enabled="true" />
      <anonymousAuthentication enabled="false" />
    </authentication>
  </security>
</system.webServer>

Then you can use this to get a UserPrincipal object of the current user:

UserPrincipal.FindByIdentity(domain, User.Identity.Name)

But you may still run into issues with the account being used since your website also needs to authenticate to AD with domain credentials.

DefaultAppPool uses an account local to the server, not recognized by AD. You can pass AD credentials in the PrincipalContext constructor, like this:

using (var ctx = new PrincipalContext(ContextType.Domain, null, "username", "password"))

I thought NetworkService uses the AD computer account to authenticate, but maybe your server is not joined to the domain? If it is not, then you will also need to specify the domain name in the PrincipalContext:

using (var ctx = new PrincipalContext(ContextType.Domain, "domain.com", "username", "password"))

It works when you run it locally in IIS Express because IIS Express runs under your credentials and uses your credentials to authenticate to AD.

Gabriel Luci
  • 38,328
  • 4
  • 55
  • 84
  • I'd like to do this in a Sigle Sign-On way. Users don't log in to the app, they just get authorized by Windows Authentication. I also changed the ApplicationPool to .NET v4.5 Classic and it didn't work either. Is there any way to do this in these circumstances? – PRHMN Oct 18 '18 at 14:10
  • Right, I missed that part of the question. I updated my answer. – Gabriel Luci Oct 18 '18 at 14:59
  • Thanks. I thought that the entire idea behind Windows Authentication is that I don't have to pass password of the user? Anyway, I don't have user's password as I only use Windows authentication. Should I create some service user for querying AD? Both server and client are part of the same domain, I tried using different ApplicationPools with NetworkService identity. – PRHMN Oct 19 '18 at 07:19
  • Ok, got it. Last missing part was HostingEnvironment.Impersonate() when before UserPrincipal.FindByIdentity, now it works. Thank you :) – PRHMN Oct 19 '18 at 08:16