PrincipalContext.ValidateCredentials failing intermittently RRS feed

  • Question

  • I am using the following simple code to perform user validation against AD using the System.DirectoryServices.AccountManagement namespace from 3.5:

    bool ADAuthClientLDAPClass::IsAuthenticated(String ^username, String ^pwd)
        static char const module[] = "ADAuthClientLDAPClass::IsAuthenticated()";
            debug("%s:%ld: Performing AD authentication for user %s", module, __LINE__, username);
            PrincipalContext ^ldsContext = gcnew PrincipalContext(ContextType::Domain);
            bool is_authenticated = ldsContext->ValidateCredentials(username, pwd, ContextOptions::SimpleBind | ContextOptions::SecureSocketLayer);
            if (is_authenticated)
                debug("%s:%ld: AD Authentication successful.  Connected Server: %s", module, __LINE__, ldsContext->ConnectedServer);
                debug("%s:%ld: AD Authentication failed.  Connected Server: %s", module, __LINE__, ldsContext->ConnectedServer);
            return is_authenticated;
        catch (Exception^ e)
            debug("%s:%ld: Caught exception %s", module, __LINE__, e->Message);    
        catch (...)
            debug("%s:%ld: Caught exception, user rejected", module, __LINE__);    
        return false;

    This seems to work quite nicely in my test environment, but I have one customer who has the product installed on their site who sees intermittent LDAP exceptions with the message "The LDAP Server is unavailable".  Searching that seems to suggest that message is pretty ubiquitous whenever anything goes wrong with the bind attempt, and it doesn't really tell me much.

    The fact that this is intermittent is what confuses me.  At the customers site, it will fail consistently for a period of time, and then work consistently for a period of time.  Perhaps this points a system or networking issue at the customer's site, but I want to find out if there is anything about the way I'm using the API that might be contributing to this or causing it.  Some specific questions:

    I am not passing the domain name to the constructor for the PrincipalContext.  Should I be?  If I do I need to make this a configuration option that each customer must set up, which is possible but would be cleaner if I didn't need to make them do that.  I believe the behavior the way it is should be that it validates against the domain that the calling thread is logged into.  This runs as a service, so that would be the domain of the service "Run as" user, which my customers can configure either to the the Local System or a specific domain user.  Either way it should be part of the right domain, I believe.  In any case I don't see why this would cause it to fail only sometimes.

    I believe this customer has multiple domain controllers, so I've considered the possibility that the call could be failing against only one of them.  How does this API decide what DC to connect to?  I'm not an AD expert, and therefore I like the simplicity of using this API but it does hide a lot of the gory details about what it is doing under the hood, but that makes it harder to figure out what's going wrong when it doesn't work.

    Is there any way of getting more information from the AccountManagement API as to why the authentication is failing?  What's the best way to diagnose this?  I guess that might be more of a networking question than an API question, but if anyone knows, or knows what forum I should ask that question, please let me know.

    Friday, March 30, 2012 10:15 PM


All replies