5

I've been trying to solve this problem all day, and I've read some conflicting information within the standard google message board answers.

What I'm trying to do is retrieve a domain user's (that is, the currently logged in user's) email address from active directory. My ASP.NET 4 website is setup for Windows Authentication and everything works fine until the active directory calls.

When I do the following, I get a COMException on the search.findAll() line. The exception message is "An operations error occured" (Very helpful message eh?) (Stripped down code for readability)

WindowsIdentity winId = (WindowsIdentity)HttpContext.Current.User.Identity;
WindowsImpersonationContext wic = null;

wic = winId.Impersonate();
using (DirectoryEntry root = new DirectoryEntry(rootQuery))
{
      String userQuery = GetUserQuery();
      DirectorySearcher searcher = new DirectorySearcher(root);
      searcher.SearchScope = SearchScope.Subtree;
      searcher.Filter = userQuery;

      SearchResultCollection results = searcher.FindAll();
      return (results[0].Properties["proxyaddresses"][0]).ToString();
}

So basically I want to impersonate the logged in user to make the call. Note this code works as expected if I pass in my credentials directly to the DirectoryEntry constructor. Also, I receive the same error if I get rid of the impersonation code and set application wide impersonation in the web config.

So I guess my question, before I waste any more time on this, is this even possible? Or do you have to specify a username and password to access AD?

BTW on my dev box I'm running IIS5, but will probably deploy to IIS6.

edit:

as requested:

rootQuery = @"LDAP://{0}.com/DC={0}, DC=com";
userQuery = @"(&(samAccountName={0})(objectCategory=person)(objectClass=user))";

with the proper domain and user specified.

Sean Carpenter
  • 7,681
  • 3
  • 37
  • 38
Erix
  • 7,059
  • 2
  • 35
  • 61

5 Answers5

5

You are trying to impersonate a user to access an external resource (external meaning not on the same server). You CAN do this, but you will need to setup delegation in active directory so that the IIS server (or your WindowsXP box for now) is trusted for delegation. Check out some of these resources to get started if this is the direction you want to go.

Alternatively, to avoid the hastle of setting up and configuring delegation properly I just create a service account in active directory and use it instead. You can either use the credentials in your code, like you said worked earlier, or use the Impersonation element in web.config to impersonate this service account: <identity impersonate="true" userName="DOMAIN\ServiceAccount" password="password"/>.

Peter
  • 9,643
  • 6
  • 61
  • 108
  • 1
    Rather than impersonate the domain account, would it work to run the app pool under this service account in IIS 6? Putting the user/password in plain text in code/web.config bothers me. – Erix Jul 19 '11 at 12:19
  • Given a change to IIS 6 I would think this would work fine. Additionally you can encrypt portions of your web.config file to avoid the plaintext issue: http://msdn.microsoft.com/en-us/library/ff647398.aspx. – Peter Jul 20 '11 at 13:20
2

As @Patricker mentions you have to enable delegation to support this scenario. Also make sure that you use an authentication mechanism that supports delegation. If you use Kerberos to authenticate the user to the web server, delegation is possible, but not with NTLM[1]. If you use basic authentication delegation is also possible (as the web server has access to username and password of the client).

Anders Abel
  • 67,989
  • 17
  • 150
  • 217
1

If I remember right, there were some challenges here if the app pool was running as Network Service vs a domain account. How is yours configured?

Also, can you post the value of rootQuery and the resultant value for userQuery?

Brian Desmond
  • 4,473
  • 1
  • 13
  • 11
1

Don't you think it has something to do with Troubleshooting Authentification problem on ASP pages

JPBlanc
  • 70,406
  • 17
  • 130
  • 175
0

Also noticed the way in the code to search LDAP looks very performance cost expensive. You might want to query LDAP using sid search, which can be found in attached link

Community
  • 1
  • 1
anIBMer
  • 1,159
  • 2
  • 12
  • 20