I've got an application that needs to be able to use the windows authentication for either the local machine or a domain. Previously, I was using PrincipalContext.ValidateCredentials, and it was working fine at first, then it started randomly returning false for correct credentials. I looked at this question and saw that people were saying that if PrincipalContext.ValidateCredentials
was under too heavy of a load, then it could start throwing exceptions, and I noticed elsewhere people were saying it was always returning false.
The question I linked suggested using LogonUser
instead from the advapi32.dll
library. That's fine, the only issue is that I'd like to be able to reliably break the PrincipalContext.ValidateCredentials
call before saying another method will work. This code produced no errors and never returns false on the same system that was returning those false negatives. I'd like to break it so I can make sure that the LogonUser
call isn't going to have the same issue.
using System;
using System.Collections.Generic;
using System.DirectoryServices.AccountManagement;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace TestAuthentication
{
class Program
{
static void Main(string[] args)
{
var credentials = new Dictionary<string, string>
{
{"Developer","rfsdev"},
{"Customer","password"},
{"Content Builder", "password"},
};
bool isBroken = false;
int maxTries = 10000;
int currentTry = 0;
while(!isBroken && currentTry < maxTries)
{
currentTry++;
foreach(var kvp in credentials)
{
isBroken = !AreCredentialsValid(kvp.Key, kvp.Value);
Console.WriteLine("Result from {0} and {1}: {2}", kvp.Key, kvp.Value, !isBroken);
if (isBroken)
{
Console.WriteLine("Found breaking case after {0} tries", currentTry);
break;
}
}
}
Console.ReadLine();
}
protected static bool AreCredentialsValid(string username, string password)
{
bool isDomain = username.Contains("\\");
string domain = isDomain ? username.Split(new char[] { '\\' })[0] : "";
username = isDomain ? username.Split(new char[] { '\\' })[1] : username;
bool credentialsValid = false;
if (isDomain)
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, domain))
credentialsValid = pc.ValidateCredentials(username, password);
else
using (PrincipalContext pc = new PrincipalContext(ContextType.Machine))
credentialsValid = pc.ValidateCredentials(username, password);
return credentialsValid;
}
}
}