This code used to work for me in order to retrieve the AD information of a user when passing ID by parameter.
public UsersDTO GetUserFromActiveDirectoryByID(string userID)
{
DirectorySearcher ds = new DirectorySearcher();
ds.Filter = "(&(objectClass=user)(objectcategory=person)(name=" + userID + "))";
SearchResultCollection results = ds.FindAll();
SearchResult userProperty = results[0];
UsersDTO user = new UsersDTO();
if (userProperty.Properties["mail"].Count > 0)
{
user.fullName = userProperty.Properties["displayname"][0].ToString();
user.email = userProperty.Properties["mail"][0].ToString();
}
return user;
}
It worked while the application service was hosted in another server, but now that it has been migrated to Azure, the FindAll command (also FindOne was tested) returns "There was an error retrieving the data.","Status":400,"Detail":"Access is denied."
You aren't setting the SearchRoot of your DirectorySearcher. The documentation for SearchRoot says:
If SearchRoot is a null reference (Nothing in Visual Basic), the search root is set to the root of the domain that your server is currently using.
If the other server was joined to the domain that you are trying to search, then that's why it was working. But that is no longer true when you're on Azure.
So you need to specify the SearchRoot to point it at your domain:
DirectorySearcher ds = new DirectorySearcher();
ds.SearchRoot = new DirectoryEntry("LDAP://example.com");
This may also introduce issue of whether you can actually access your domain controllers from Azure. You may need to open firewall rules to allow it, depending on how your environment is setup.
Related
I want to list the all mail list or search a mail id present in my Active directory so I have used the DirectorySearcher like following and working in my local system if I run it via visual studio but not working when I publish or deploy these code to an IIS server.
My C# Code,
[HttpGet]
public JsonResult getADEmail(string query = "")
{
DirectorySearcher dirSearcher = new DirectorySearcher();
dirSearcher.Filter = "(&(objectClass=user)(objectcategory=person)(mail=" + query + "*))";
SearchResult srEmail = dirSearcher.FindOne();
SearchResultCollection SearchResultCollection = dirSearcher.FindAll();
string propName = "mail";
ResultPropertyValueCollection valColl = srEmail.Properties[propName];
List<string> results = new List<string>();
foreach (SearchResult sr in SearchResultCollection)
{
ResultPropertyValueCollection val = sr.Properties[propName];
results.Add(val[0].ToString());
}
return Json(results);
}
Directory Path in my local,
"LDAP://DC=arcadis-nl,DC=local" from (dirSearcher.SearchRoot.Path)
The IIS is on another server: 154:139:1:150
Where I did go wrong?What should I do to resolve this issue?.
It seems like a directory permissions problem.Few things to check:
Does the user (or machine) that is connecting to the IIS server have permissions to perform the query?
In these kind of scenario , we have to set the identity of the application pool to a user who has access to the directory.
Additional reference:
https://www.codeproject.com/Tips/599697/Get-list-of-Active-Directory-users-in-Csharp
Hope it helps.
I wrote a small app to check AD group members. When I execute the following code on my pc, It works well, the SearchResult contains the "member" property, however when I run the same exe on the server or on an another computer the "member" property is missing. The usnchanged and usncreated will be different also. I run the exe with the same user on every pc. What can cause this?
...
using (DirectorySearcher searcher = new DirectorySearcher())
{
searcher.CacheResults = false;
searcher.Filter = "(&(objectClass=group)(cn=" + ADName + "))";
searcher.SizeLimit = int.MaxValue;
searcher.PageSize = int.MaxValue;
if (!DirectoryEntry.Exists(ADPath))
{
return null;
}
searcher.SearchRoot = new DirectoryEntry(ADPath);
using (SearchResultCollection collection = searcher.FindAll())
{
if (collection.Count == 1)
{
return collection[0];
}
}
}
...
The group membership data is not replicated to the global catalog. The query might work sometimes, if you happen to connect to the domain controller with the actual membership data. On other machines, you probably connect to other domain controllers, of different domains, where the information is not available.
You might want to connect to a domain controller in the actual domain, not to the global catalog.
I have some code that retrieves the Active Directory groups that a user is a member of. On localhost it returns the correct results, but when deployed to a another computer (web server on same network) it returns much less results.
I am specifying AD server and a special user name and password I was given by administrators to access.
DirectoryEntry de = new DirectoryEntry("LDAP://***:389", "***", "***");
DirectorySearcher ds = new DirectorySearcher(de);
ds.Filter = "(&((&(objectCategory=Person)(objectClass=User)))(samaccountname=" + search + "))";
ds.SearchScope = SearchScope.Subtree;
ds.PropertiesToLoad.Add("*");
SearchResult rs = ds.FindOne();
if (rs != null)
{
if (rs.GetDirectoryEntry().Properties["memberof"].Value != null)
//rest of code removed
I also tried a different method and the results were also different...
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, "***, "***", "***"))
{
UserPrincipal user = UserPrincipal.FindByIdentity(pc, name);
if (user != null)
{
List<string> groups = new List<string>();
PrincipalSearchResult<Principal> groups2 = user.GetAuthorizationGroups();
//rest of code removed
I would have thought that by specifying a user name and password that the result should be the same. Any idea why this is happening?
These are different because they're retrieving different datasets. The memberOf attribute is constructed on the fly and it will give you the groups the user is a /direct/ member of. The GetAuthorizationGroups() call, on the other hand, will give you all the security groups that the user is transitively a member of. It does this by looking at the tokenGroups attribute in AD.
I want to connect to our local Active Directory with C#.
I've found this good documentation.
But I really don't get how to connect via LDAP.
Can somebody of you explain how to use the asked parameters?
Sample Code:
static DirectoryEntry createDirectoryEntry()
{
// create and return new LDAP connection with desired settings
DirectoryEntry ldapConnection = new DirectoryEntry("rizzo.leeds-art.ac.uk");
ldapConnection.Path = "LDAP://OU=staffusers,DC=leeds-art,DC=ac,DC=uk";
ldapConnection.AuthenticationType = AuthenticationTypes.Secure;
return ldapConnection;
}
I just have the Hostname and the IP Address of our Active Directory Server. What does DC=xxx,DC=xx and so on mean?
DC is your domain. If you want to connect to the domain example.com than your dc's are: DC=example,DC=com
You actually don't need any hostname or ip address of your domain controller (There could be plenty of them).
Just imagine that you're connecting to the domain itself. So for connecting to the domain example.com you can simply write
DirectoryEntry directoryEntry = new DirectoryEntry("LDAP://example.com");
And you're done.
You can also specify a user and a password used to connect:
DirectoryEntry directoryEntry = new DirectoryEntry("LDAP://example.com", "username", "password");
Also be sure to always write LDAP in upper case. I had some trouble and strange exceptions until I read somewhere that I should try to write it in upper case and that solved my problems.
The directoryEntry.Path Property allows you to dive deeper into your domain. So if you want to search a user in a specific OU (Organizational Unit) you can set it there.
DirectoryEntry directoryEntry = new DirectoryEntry("LDAP://example.com");
directoryEntry.Path = "LDAP://OU=Specific Users,OU=All Users,OU=Users,DC=example,DC=com";
This would match the following AD hierarchy:
com
example
Users
All Users
Specific Users
Simply write the hierarchy from deepest to highest.
Now you can do plenty of things
For example search a user by account name and get the user's surname:
DirectoryEntry directoryEntry = new DirectoryEntry("LDAP://example.com");
DirectorySearcher searcher = new DirectorySearcher(directoryEntry) {
PageSize = int.MaxValue,
Filter = "(&(objectCategory=person)(objectClass=user)(sAMAccountName=AnAccountName))"
};
searcher.PropertiesToLoad.Add("sn");
var result = searcher.FindOne();
if (result == null) {
return; // Or whatever you need to do in this case
}
string surname;
if (result.Properties.Contains("sn")) {
surname = result.Properties["sn"][0].ToString();
}
ldapConnection is the server adres: ldap.example.com
Ldap.Connection.Path is the path inside the ADS that you like to use insert in LDAP format.
OU=Your_OU,OU=other_ou,dc=example,dc=com
You start at the deepest OU working back to the root of the AD, then add dc=X for every domain section until you have everything including the top level domain
Now i miss a parameter to authenticate, this works the same as the path for the username
CN=username,OU=users,DC=example,DC=com
Introduction to LDAP
If your email address is 'myname#mydomain.com', try changing the createDirectoryEntry() as below.
XYZ is an optional parameter if it exists in mydomain directory
static DirectoryEntry createDirectoryEntry()
{
// create and return new LDAP connection with desired settings
DirectoryEntry ldapConnection = new DirectoryEntry("myname.mydomain.com");
ldapConnection.Path = "LDAP://OU=Users, OU=XYZ,DC=mydomain,DC=com";
ldapConnection.AuthenticationType = AuthenticationTypes.Secure;
return ldapConnection;
}
This will basically check for com -> mydomain -> XYZ -> Users -> abcd
The main function looks as below:
try
{
username = "Firstname LastName"
DirectoryEntry myLdapConnection = createDirectoryEntry();
DirectorySearcher search = new DirectorySearcher(myLdapConnection);
search.Filter = "(cn=" + username + ")";
....
I'm trying to use the DomainServices class to retrieve a list of OU's from my Active Directory.
Here's my code:
public List<OrganizationalUnit> FindOrganizationalUnits(string domainName, string domainExtension, string parentOrganizationUnit)
{
string tmpDirectory = String.Format("LDAP://ou={0},dc={1},dc={2}",
parentOrganizationUnit,
domainName,
domainExtension
);
DirectoryEntry directory = new DirectoryEntry(tmpDirectory);
DirectorySearcher searcher = new DirectorySearcher(directory);
searcher.Filter = "(objectClass=organizationalUnit)";
searcher.SearchScope = SearchScope.Subtree;
searcher.PropertiesToLoad.Add("displayName");
var organizationalUnits = new List<OrganizationalUnit>();
foreach (SearchResult result in searcher.FindAll())
{
//I just create and return a new OrganizationalUnit object based on the SearchResult result.
organizationalUnits.Add(new OrganizationalUnit(result));
}
return organizationalUnits;
}
Is there some configuration I have to set on my server end to let me use DirectoryServices to query it's AD objects?
Thanks for the help.
What type of app are you running this code from? AD queries have to be made from an authenticated resource. You can either use the current credentials of the user, or pass in a new name/password.
Services usually don't have any issue, running under LocalSystem, but if this is a web app running under IIS standard permissions, it might cause an issue.
Try adding some credentials where you're instantiating your DirectoryEntry class.