user26218
user26218

Reputation: 65

ADAM authentication w/ ADAM user and simple bind

I've followed the ADAM Step by Step Guide from Microsoft and setup an ADAM instance on my local machine. I'm attempting to authenticate using the "Mary Baker" account, but every time I get a COM exception on the if (entry.Guid != null) line below. The exception states that there's an unknown user name or bad password.

However, I can use the ldp utility to connect to ADAM and successfully perform a simple bind - so I know that the user name both exists, and I have the correct password.

Additionally, I have set the msDS-UserAccountDisabled property on the user to false, and added the user to both the Administrators and Readers roles.

Any thoughts?

    path = "LDAP://localhost:50000/O=Microsoft,c=US";
    userId = "CN=Mary Baker,OU=ADAM users,";
    password = "Mary@101";

    DirectoryEntry entry = new DirectoryEntry(path, userId, password, AuthenticationTypes.None);
    if (entry.Guid != null)
        LoadWelcomeScreen();

Thanks.

Upvotes: 1

Views: 4910

Answers (3)

Kwex
Kwex

Reputation: 4020

Thanks Ryan for your tip on displayName. Posted my test class on my local ADAM instance for anyone who might be interested.

    [TestMethod]
    public void CreateUserAccount()
    {
        var username = "amurray";
        var password = "ADAMComplexPassword1234";
        var firstname = "Andy";
        var lastname = "Murray";

        const AuthenticationTypes authTypes = AuthenticationTypes.Signing |
                                              AuthenticationTypes.Sealing |
                                              AuthenticationTypes.Secure;

        var ldapPath = "LDAP://localhost:389/OU=MyProject,OU=Applications,DC=Company,DC=ADAM";
        using (var dirEntry = new DirectoryEntry(ldapPath, "MyPC\\adamuser", "Password1!", authTypes))
        {
            DirectoryEntry user = null;
            const int ADS_PORT = 389;
            const long ADS_OPTION_PASSWORD_PORTNUMBER = 6;
            const long ADS_OPTION_PASSWORD_METHOD = 7;
            const int ADS_PASSWORD_ENCODE_CLEAR = 1;

            try
            {
                user = dirEntry.Children.Add(string.Format("CN={0} {1}", firstname, lastname), "user");
                user.Properties["displayName"].Value = username;
                user.Properties["userPrincipalName"].Value = username;
                user.Properties["msDS-UserAccountDisabled"].Value = false;
                user.Properties["msDS-UserDontExpirePassword"].Value = true;
                user.CommitChanges();
                var userid = user.Guid.ToString();

                // Set port number, method, and password.
                user.Invoke("SetOption", new object[]{ADS_OPTION_PASSWORD_PORTNUMBER,ADS_PORT});
                user.Invoke("SetOption", new object[]{ADS_OPTION_PASSWORD_METHOD,ADS_PASSWORD_ENCODE_CLEAR});

                user.Invoke("SetPassword", new object[] {password});
                user.CommitChanges();
                user.Close();
            }
            catch (Exception e)
            {
                var msg = e.GetBaseException().Message;
                Console.WriteLine(e);
                System.Diagnostics.Debug.Print(msg);
            }                
        }
    }


    [TestMethod]
    public void TestUserAuthentication()
    {
        try
        {
            var ldsContext = new PrincipalContext(ContextType.ApplicationDirectory, "localhost:389",
                                                  "OU=MyProject,OU=Applications,DC=Company,DC=ADAM",
                                                  ContextOptions.SimpleBind);

            // Returns true if login details are valid
            var isValid = ldsContext.ValidateCredentials("amurray", "ADAMComplexPassword1234", ContextOptions.SimpleBind);
        }
        catch (Exception e)
        {
            var msg = e.GetBaseException().Message;
            Console.WriteLine(e);
            System.Diagnostics.Debug.Print(msg);
        }
    }

Upvotes: 1

Ryan Sweet
Ryan Sweet

Reputation: 46

ADAM stores the unique identifier for a user in the displayName attribute of the user class. They need to be unique in the ADAM instance for the user to authenticate. If two users both had their displayName attribute set to 'jsmith' then neither user could authenticate in ADAM.

Use the ldp utility to query the displayName for Mary Baker. It could be something like 'mbaker'. Use that value as the userId in the given code.

Upvotes: 2

Josh Kelley
Josh Kelley

Reputation: 58442

I haven't used ADAM or System.DirectoryServices, but I do have experience with LDAP and AD; hopefully the following is applicable.

I've never seen a user ID given in that format before. (It looks like some sort of relative DN, as indicated by the trailing comma?) Have you tried specifying the user ID as a full DN (as required by standard LDAP) or as a bare username (if ADAM supports that)?

When diagnosing network protocol problems like this (seeing if the my program is doing what I think I'm telling it to do and seeing how what it's doing compares to what a functioning program is doing), I've found it helpful to run Wireshark for both the non-functioning and the functioning operation to see how they differ. If you've never used Wireshark, it hopefully won't be too hard to get started:

  1. Download, install, and start the software.
  2. Under Capture, click Options.
  3. Set Interface to either localhost / loopback or to your Ethernet interface. (I don't think that loopback works as expected on Windows ; you'll probably want to pick your Ethernet interface and update your LDAP URL in your C# code to use your hostname rather than localhost.)
  4. Under Capture Filter, enter "tcp port 50000" (no quotes).
  5. Click Start, run your connect operation, then go under the Capture menu and click Stop.

Wireshark can analyze the protocol for you, so you don't have to be too familiar with the protocol details yourself, although the more you know, the easier it is to interpret all of the details. You can fire up a couple of instances of Wireshark to easily compare two different captures (your code and LDP).

Upvotes: 0

Related Questions