We are trying to extract and display a UserProxyPrincipal from AD-LDS server onto a web application.
Ideally a userProxyFull object from ADLDS/ ADAM with System.DirectoryServices.AccountManagement library.
We can get the information as we expected with DirectorySearcher but extended PrincipalContext.FindByIdentity does not work.
Following works
DirectoryEntry dirEntry = new DirectoryEntry(@"LDAP://" + server + "/" + ou + "");
dirEntry.AuthenticationType = AuthenticationTypes.Secure | AuthenticationTypes.SecureSocketsLayer;
DirectorySearcher dirSearch = new DirectorySearcher(dirEntry);
dirSearch.Filter = $"(cn={searchUser})";
dirEntry.Username = usr;
dirEntry.Password = pwd;
dirSearch.PageSize = 100;
SearchResult srhResult = dirSearch.FindOne();
dirSearch.Dispose();
Following Doesn't
using (var context = new PrincipalContext(ContextType.ApplicationDirectory, server, ou, ContextOptions.Negotiate | ContextOptions.SecureSocketLayer, usr, pwd))
{
//var response = context.ValidateCredentials(usr, pwd); //<--- fails here
using (var user = UserProxyPrincipal.FindByIdentity(context, searchUser)) //<--- fails here with error "The server is not operational"
{
if (user != null)
{
}
}
}
//Following is the code I used for extending UserPrincipal class to retrive userProxyFull objects from AD LDS/ADAM.
namespace System.DirectoryServices.AccountManagement
{
[DirectoryRdnPrefix("CN")]
[DirectoryObjectClass("userProxyFull")]
public class UserProxyPrincipal : UserPrincipal
{
public UserProxyPrincipal(PrincipalContext context)
: base(context) { }
public UserProxyPrincipal(PrincipalContext context, string samAccountName, string password, bool enabled)
: base(context, samAccountName, password, enabled) { }
public static new UserProxyPrincipal FindByIdentity(PrincipalContext context, string identityValue)
{
var vvv = FindByIdentityWithType(context, typeof(UserProxyPrincipal), identityValue);
return (UserProxyPrincipal)vvv;
}
public static new UserProxyPrincipal FindByIdentity(PrincipalContext context, IdentityType identityType, string identityValue)
{
return (UserProxyPrincipal)FindByIdentityWithType(context, typeof(UserProxyPrincipal), identityType, identityValue);
}
[DirectoryProperty("objectSid")]
public string ObjectSid
{
get
{
var values = ExtensionGet("objectSid");
return ((values != null) && (values.Length > 0) ? values[0].ToString() : null);
}
set { ExtensionSet("objectSid", value); }
}
[DirectoryProperty("name")]
public new string Name
{
get
{
var values = ExtensionGet("name");
return ((values != null) && (values.Length > 0) ? values[0].ToString() : null);
}
set { ExtensionSet("name", value); }
}
}
}
Configuration
We are running one ADLDS instance on two windows server 2012 R2, with replication and load balancing between them.
The ADLDS servers are load balanced with a BigIP F5 load balancer.
The ADLDS instance is accessed via load balanced alias.
I am using Windows server 2012 R2
I am using Any CPU but no changes with or without "Prefer 32-bit"
since our ADLDS is exposed only through load balanced alias direct access to servers is blocked.
Regression?
I am using Dot Net framework 4.7.2 but when i changed to previous platform versions the error was the same.
Other information
DirectorySearcher works because it considers the load balanced alias as the actual server name. Where as System.DirectoryServices.AccountManagement libraries ADUtils.cs tries and gets the actual server name, it retrieves the actual server name and tried to connect to i but unfortunately the direct server access is blocked and hence the issue based on my understanding. I inspected the network traffic and DirectoryEntry never connects to server directly it honours the clustered alias name but PrincipalContext.FindUserbyIdentity doesnt.
Description
We are trying to extract and display a UserProxyPrincipal from AD-LDS server onto a web application. Ideally a userProxyFull object from ADLDS/ ADAM with System.DirectoryServices.AccountManagement library. We can get the information as we expected with DirectorySearcher but extended PrincipalContext.FindByIdentity does not work.
Following works
Following Doesn't
Configuration
Regression?
Other information
DirectorySearcher works because it considers the load balanced alias as the actual server name. Where as System.DirectoryServices.AccountManagement libraries ADUtils.cs tries and gets the actual server name, it retrieves the actual server name and tried to connect to i but unfortunately the direct server access is blocked and hence the issue based on my understanding. I inspected the network traffic and DirectoryEntry never connects to server directly it honours the clustered alias name but PrincipalContext.FindUserbyIdentity doesnt.
internal static string GetServerName(DirectoryEntry de) { UnsafeNativeMethods.IAdsObjectOptions objOptions = (UnsafeNativeMethods.IAdsObjectOptions)de.NativeObject; return (string)objOptions.GetOption(0 /* == ADS_OPTION_SERVERNAME */); }