Adrian H
Adrian H

Reputation: 599

PrincipalContext ValidateCredentials fails for some users when used in a Web API

I have a really strange behavior that I am trying to figure out.

I have a ASP.NET 4.5 Web API running under IIS that is used to validate users credentials against Active Directory as per the code below.

It works for some users in the AD but will always return false for other users in the AD. From the logging with my custom messageHandler I know it is getting to the messageHandler.WriteSuccess part. So I know it is not throwing an exception.

I wrote a windows forms desktop app using the same code to run on the web server to help troubleshoot the issue but it validates all users correctly.

This lead me to believe it might be an issue that the ASP.NET Web API is running as network services. I changed the app pool to use the same identity as I logged into the web server as but it made no difference.

Why would the exact same code validate users correctly in a windows forms app but only validate some users correctly in a ASP.net Web API.

As a workaround I have the network admin creating brand new AD users for the users that fail to login. This is working. There has to be some difference between the AD users that fail and the AD users that are successful.

Also it is very strange that the same code behaves differently when run as a desktop app compared to running IIS.

Any ideas or how to further troubleshoot this? The server is Windows Server 2008 R2.

PrincipalContext pc = null;
try
{
    pc = new PrincipalContext(ContextType.Domain, domain);

    var success = pc.ValidateCredentials(username, password);
    if (loggingEnabled)
    {

        messageHandler.WriteSuccess(
            username,
            HistoryLogEntry.OperationType.ActiveDirectory,
            HistoryLogEntry.RequestType.ActiveDirectoryAuthenticate, success.ToString());
    }
    return success;

}
catch (PrincipalServerDownException ex)
{
    var displayMessage = string.Format("Please check your Web Service settings. {0} {1}", ex.Message,
        ex.InnerException == null ? "" : ex.InnerException.Message);

    messageHandler.WriteHistory(
        username,
        HistoryLogEntry.OperationType.ActiveDirectory,
        HistoryLogEntry.RequestType.ActiveDirectoryAuthenticate,
        ex, displayMessage);
    messageHandler.ThrowLastAsHttpError();

    return false;
}
finally
{
    if (pc != null)
    {
        pc.Dispose();
    }
}

Upvotes: 1

Views: 790

Answers (1)

Adrian H
Adrian H

Reputation: 599

Silly mistake on my part.

The web service API exposes the validate credentials method as a GET request.

You must remember to URL Encode the username and password portions.

Especially the password as it can contain values which will mess up the query.

The people with complex passwords were failing. Where the simple passwords were ok.

Edit: I am also changing the method to a POST to avoid users forgetting or using the wrong encoding mechanism.

Upvotes: 1

Related Questions