UserPrincipal.FindByIdentity Permissions

15

I'm attempting to use the .NET System.DirectoryServices.AccountManagement library to obtain the UserPrincipal for a particular Active Directory user.

I've got the following code:

PrincipalContext context = new PrincipalContext(ContextType.Domain, "DomainName");
userPrincipal = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, username);

This code is running as a valid domain user, but when I execute it I get the following exception:

System.DirectoryServices.DirectoryServicesCOMException (0x8007052E): Logon failure: unknown user name or bad password.

What's interesting is that I can make the following call, using the same context, without a problem:

context.ValidateCredentials(username, password, ContextOptions.Negotiate)

Ideas?

c#
.net
active-directory
ldap
directoryservices
asked on Stack Overflow Aug 26, 2010 by RMD • edited Mar 1, 2011 by Forgotten Semicolon

2 Answers

12

You need to use the the PrincipalContext constructor that takes username and password.

The reason that Validate works is because its using the provided credentials to bind to the directory.

answered on Stack Overflow Mar 1, 2011 by Nate
3

It sounds like you have a stored network credentials. In Windows, you can specify to use a different network credentials when trying to reach a network resources. I can reproduce exactly the same problem as you are seeing by setting up a wrong network credentials.

Assuming your domain is called yourdomain.com, you can tell Windows to always use a specific username and password whenever it talks to any computers with suffice yourdomain.com.

=== Windows 7/2008 ===

  1. Launch the "Crendentail Manager".
  2. Under Windows credentials section, click Add a Windows credentials
  3. In network address, put in *.yourdomain.com
  4. In username and password, put in a wrong username or wrong password

=== Windows XP/2000/2003 ===

  1. Click Start and Run
  2. Type in control keymgr.dll
  3. Click Add button on "Stored User Names and Passwords" dialog
  4. In server text box, put in *.yourdomain.com
  5. In username and password, put in wrong username or wrong password

If this is really the problem that you are facing, the easy fix is to remove the stored passwords.

Why does context.ValidateCredentials(username, password, ContextOptions.Negotiate) work? It's simply because you are initializing another Kerberos/NTLM authentication since you provides uername and password again. Under the hood, if Kerberos is chosen, it would send the domain controller the provided username and password and exchange for a Kerberos TGT ticket. Then, your machine get a service ticket on the LDAP server using this TGT ticket. Then, your machine will send this service ticket to the LDAP server. Note that this service ticket won't be retained in the current logon session.

Why UserPrincipal.FindByIdentity doesn't work? If you don't have any stored password, normally it should work because Windows will just use the current logon user TGT ticket to exchange for the LDAP server service ticket. There is no username/password validation process involved. However, if you do have a bad username password, Windows would think it shouldn't use the current logon user TGT ticket. Instead, it should get a new TGT ticket using the stored network password. That's the reason you are seeing System.DirectoryServices.DirectoryServicesCOMException (0x8007052E): Logon failure: unknown user name or bad password.

answered on Stack Overflow Mar 2, 2011 by Harvey Kwok

User contributions licensed under CC BY-SA 3.0