Get Department of user from AD - c#

Working with Active directory in an ASP.net CORE MVC website,
I can get many user property like diplayName, emailAdress...
But I cannot find the departement of the user.
Get user informations :
UserPrincipal user = UserPrincipal.FindByIdentity(new PrincipalContext(ContextType.Domain), Environment.UserName);
But user haven't a property "Department".
I've try :
DirectoryEntry directoryEntry = user.GetUnderlyingObject() as DirectoryEntry;
var property = "department";
if (directoryEntry.Properties.Contains(property))
{
var dep = directoryEntry.Properties[property].Value.ToString();
}
No departement property neither.
EDIT
Here's a list of properties available : "objectClass, cn, sn, title, description, userCertificate, givenName, distinguishedName, instanceType, whenCreated, whenChanged, displayName, uSNCreated, memberOf, uSNChanged, proxyAddresses, homeMDB, mDBUseDefaults, mailNickname, name, objectGUID, userAccountControl, badPwdCount, codePage, countryCode, badPasswordTime, lastLogon, pwdLastSet, primaryGroupID, objectSid, accountExpires, logonCount, sAMAccountName, sAMAccountType, showInAddressBook, legacyExchangeDN, userPrincipalName, objectCategory, dSCorePropagationData, lastLogonTimestamp, textEncodedORAddress, mail and Lot of msExchange"

This works for me (using a mixture of AccountManagement and DirectoryServices):
var ad = new PrincipalContext(ContextType.Domain, DOMAIN);
var u = new UserPrincipal(ad) {SamAccountName = Environment.UserName};
using (var search = new PrincipalSearcher(u))
{
var user = (UserPrincipal) search.FindOne();
DirectoryEntry dirEntry = (DirectoryEntry)user.GetUnderlyingObject();
string dept = dirEntry.Properties["Department"].Value.ToString();
Console.WriteLine(dept);
}
This requires the following using:
using System;
using System.DirectoryServices;
using System.DirectoryServices.AccountManagement;

To search for an employee's unit
Use value
Department = directoryEntry.Properties["subdivision"].Value as string,

Related

Obtaining 'Canonical name of object' that you see in the AD Object tab

Trying to get the 'Canonical name of object' found in the Object tab of a users account in AD.
I can get the distinguishedName and cn attributes, but neither is in the correct format, for example:
I don't want: CN=John Smith,OU=Users,OU=Organisation,OU=Tenants,DC=domain,DC=local
I do want: domain.local/Tenants/Organisation/Users/John Smith
Any assistance is appreciated!
Ended up getting this working via:
public string getCanonicalName(string cDomain, string cUsername)
{
string canonicalName = String.Empty;
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, cDomain);
UserPrincipal user = UserPrincipal.FindByIdentity(ctx, cUsername);
using (DirectoryEntry de = user.GetUnderlyingObject() as DirectoryEntry)
{
de.RefreshCache(new string[] { "canonicalName" });
canonicalName = de.Properties["canonicalName"].Value as string;
}
return canonicalName;
}

How can I get all Active Directory Users username and display name

I have an Intranet application using ASP.Net MVC 5
I need to query all Active directory users username
I searched the net I found 2 useful post:
1- How can I get a list of users from active directory?
2- http://www.codeproject.com/Tips/599697/Get-list-of-Active-Directory-users-in-Csharp
When I query I can get the Name property but I can't get the active directory usernames
any solutions that I can get all Active directory users username?
bellow is my code:
List<TempUsers> MyTempUser = new List<TempUsers>();
var context = new PrincipalContext(ContextType.Domain, "MyDomain.com");
var searcher = new PrincipalSearcher(new UserPrincipal(context));
foreach (var result in searcher.FindAll())
{
DirectoryEntry de = result.GetUnderlyingObject() as DirectoryEntry;
MyTempUser.Add(new TempUsers { UserName = de.Properties["Name"].Value.ToString() });
}
The property name you're looking for is sAMAccountName.
Here's a list of the available attributes.
I did it this way it worked great:
1- Add reference to Active Directory services DLL
2- Add using in your controller:
using System.DirectoryServices.AccountManagement;
than I created a function to store All Active directory users in database table
bellow is the code hope help someone needs it.
public ActionResult Create()
{
List<MyADUsers> TheAllADUsers = new List<MyADUsers>();
var context = new PrincipalContext(ContextType.Domain, "MyDoman.org");
var searcher = new PrincipalSearcher(new UserPrincipal(context));
foreach (var result in searcher.FindAll())
{
TheAllADUsers.Add(new MyADUsers { ADUserName = result.SamAccountName, AD_IsMemberOf = result.UserPrincipalName, FullName = result.Name });
}
db.MyADUsersContext.AddRange(TheAllADUsers);
db.SaveChanges();
return View();
}

Trying to read login name from Active Directory returning null

DirectoryEntry DirEntry = new DirectoryEntry("LDAP://" + domain, null, null, AuthenticationTypes.None);
DirectorySearcher search = new DirectorySearcher(DirEntry);
search.Filter = String.Format("(SAMAccountName={0})", "my_login_name");
search.PropertiesToLoad.Add("cn");
SearchResult result1 = search.FindOne();
myDataTable Users = new myDataTable();
DataRow User;
foreach (SearchResult i in search.FindAll())
{
DirectoryEntry CurrentDirEntry;
User = Users.NewUserRow();
CurrentDirEntry = i.GetDirectoryEntry();
User.FirstName = (string)CurrentDirEntry.Properties["givenname"].Value;
User.LastName = (string)CurrentDirEntry.Properties["sn"].Value;
User.UserName = (string)CurrentDirEntry.Properties["sAMAccountName"].Value;
User.Email = (string)CurrentDirEntry.Properties["mail"].Value;
Users.AddUserRow(User);
}
I'm trying to read some properties from active directory but the value for
sAMAccountName
is always returned as null, i'm wondering why this is so since its being matched in the search filter. Could it be related to access privileges?
I want to return the FirstName, LastName, Email and login Name. I'm getting other properties except login name.
If you're on .NET 3.5 and up, you should check out the System.DirectoryServices.AccountManagement (S.DS.AM) namespace. Read all about it here:
Managing Directory Security Principals in the .NET Framework 3.5
MSDN docs on System.DirectoryServices.AccountManagement
Basically, you can define a domain context and easily find users and/or groups in AD:
// set up domain context
using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain))
{
// find a user
UserPrincipal user = UserPrincipal.FindByIdentity(ctx, my_login_name);
if(user != null)
{
// do something here....
string samAccountName = user.SamAccountName;
}
}
The new S.DS.AM makes it really easy to play around with users and groups in AD!
Update: if you need to search by fields that aren't handled by the .FindByIdentity() call, then you need to use the PrincipalSearcher and a "query-by-example" principal to do your searching:
// create your domain context
using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain))
{
// define a "query-by-example" principal - here, we search for a UserPrincipal
// and with the first name (GivenName) of "Bruce" and a last name (Surname) of "Miller"
UserPrincipal qbeUser = new UserPrincipal(ctx);
qbeUser.GivenName = "Bruce";
qbeUser.Surname = "Miller";
// create your principal searcher passing in the QBE principal
PrincipalSearcher srch = new PrincipalSearcher(qbeUser);
// find all matches
foreach(var found in srch.FindAll())
{
// do whatever here - "found" is of type "Principal" - it could be user, group, computer.....
}
}
Could it be the spacing in ["sAMAccountName "] of :
User.UserName = (string)CurrentDirEntry.Properties["sAMAccountName "].Value;
Try this one , I used it before
VB
Dim myDe As New DirectoryEntry("LDAP://DOMAIN.LOCAL")
Dim deSearcher As New DirectorySearcher(myDe)
Dim userDE As DirectoryEntry
Dim email As String = ""
Try
deSearcher.Filter = "(&(sAMAccountName=" & UserName & "))"
userDE = deSearcher.FindOne().GetDirectoryEntry()
email = userDE.Properties("mail").Value
Catch ex As Exception
End Try
C#
DirectoryEntry myDe = new DirectoryEntry("LDAP://DOMAIN.LOCAL");
DirectorySearcher deSearcher = new DirectorySearcher(myDe);
DirectoryEntry userDE = default(DirectoryEntry);
string email = "";
try {
deSearcher.Filter = "(&(sAMAccountName=" + UserName + "))";
userDE = deSearcher.FindOne().GetDirectoryEntry();
email = userDE.Properties("mail").Value;
} catch (Exception ex) {}
I'm not sure how C# handles it but I've seen LDAP-libs returning attribute names all in lower case. So it might help to simply call for samaccountname instead of sAMAccountName.

Trouble Authenticating ASP.NET Users Against Active Directory

I replaced our domain name with "demo"... please ignore missing commas and such in the image below.
My question is as follows:
I want to authenticate the SBSUsers in my ASP.NET web application. I cannot figure out what my active directory path needs to be in order to get it to work...
When I set it as follows, it fails to authenticate (I assume because my users are not under that path)... but it doesn't give me an error:
string adPath = "LDAP://ac-dc01.demo.local:389/CN=Configuration,DC=demo,DC=local";
string domainAndUsername = domain + #"\" + username;
DirectoryEntry entry = new DirectoryEntry(adPath, domainAndUsername, pwd);
// Bind to the native AdsObject to force authentication.
Object obj = entry.NativeObject;
DirectorySearcher search = new DirectorySearcher(entry);
search.Filter = "(SAMAccountName=" + username + ")";
search.PropertiesToLoad.Add("cn");
SearchResult result = search.FindOne();
if (null == result)
{
return false;
}
// Update the new path to the user in the directory
adPath = result.Path;
_filterAttribute = (String)result.Properties["cn"][0];
When I set it to what I think it should be, it errors on the entry.NativeObject line.
string adPath = "ldap://ac-dc01.demo.local:389/OU=SBSUsers,OU=Users,OU=MyBusiness,DC=demo,DC=local";
Any ideas? Do I need to open it up for "global" access somehow? If so, how would I go about doing that?
I was able to successfully connect using another piece of software...
this is what you can try.. also are you sure that your DC=Demo and DC=Local those look like OU's to me
const string Domain = "ServerAddress:389";
const string constrParts = #"OU=Users,DC=domain,DC=com";
const string Username = #"someusername";
PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, Domain, constrParts);
UserPrincipal userPrincipal = UserPrincipal.FindByIdentity(principalContext, username);
This is how we connect to our AD and it works great:
<yourConfig>LDAP://ADServerName/OU=GROUPNAME,DC=domainName,DC=com</YourConfig>
And here is a sample code on how you can validate a user:
using (PrincipalContext oPrincipalContext = new PrincipalContext(ContextType.Domain,
ENTER YOUR DOMAIN NAME,
This is where the config that I mentioned above comes in,
ContextOptions.Negotiate,
ENTER YOUR AD SERVICE NAME,
ENTER YOUR AD PASSWORD))
{
UserPrincipal oUser = UserPrincipal.FindByIdentity(oPrincipalContext, THE USERNAME THAT YOU WANT TO VALIDATE);
if (oUser != null)
{
oADAcct = new CUserADAcct();
oADAcct.dumpAcctAttrs(oUser);
}
}

Ldap connection in .net C#

I have an application where I can send emails. Now am asked to use ldap to authenticate the user email. Am very new to this concept. I have been given a ldap server link. No idea how to proceed with that. Any article or hits will be greatly helpful.
Here is the code am trying with
public static UserDetail GetUserDetails(string EmailId, string domainName)
{
UserDetail userDetail = new UserDetail();
try
{
string filter = string.Format("(&(ObjectClass={0})(sAMAccountName={1}))", "person", EmailId);
string[] properties = new string[] { "fullname" };
DirectoryEntry adRoot = new DirectoryEntry("LDAP://" + domainName, null, null, AuthenticationTypes.Secure);
DirectorySearcher searcher = new DirectorySearcher(adRoot);
searcher.SearchScope = SearchScope.Subtree;
searcher.ReferralChasing = ReferralChasingOption.All;
searcher.PropertiesToLoad.AddRange(properties);
searcher.Filter = filter;
SearchResult result = searcher.FindOne();
DirectoryEntry directoryEntry = result.GetDirectoryEntry();
string displayName = directoryEntry.Properties["displayName"[0].ToStrin();
string firstName = directoryEntry.Properties["givenName"][0].ToString();
string lastName = directoryEntry.Properties["sn"][0].ToString();
string emailId = directoryEntry.Properties["mail"][0].ToString();
userDetail.EmailId = emailId;
}
catch (Exception)
{
}
return userDetail;
}
I want to achieve it on click of search button. How do I call the method and pass variables.
If you're on .NET 3.5 or newer, you can use a PrincipalSearcher and a "query-by-example" principal to do your searching:
// create your domain context
PrincipalContext ctx = new PrincipalContext(ContextType.Domain);
// define a "query-by-example" principal - here, we search for a UserPrincipal
// and with the e-mail of "bruce#example.com"
UserPrincipal qbeUser = new UserPrincipal(ctx);
qbeUser.EmailAddress = "bruce#example.com";
// create your principal searcher passing in the QBE principal
PrincipalSearcher srch = new PrincipalSearcher(qbeUser);
// try to find that user
UserPrincipal found = srch.FindOne() as UserPrincipal;
if(found != null)
{
// do whatever here - "found" is the user that matched the e-mail given
}
else
{
// there wasn't any user with that e-mail address in your AD
}
If you haven't already - absolutely read the MSDN article Managing Directory Security Principals in the .NET Framework 3.5 which shows nicely how to make the best use of the new features in System.DirectoryServices.AccountManagement. Or see the MSDN documentation on the System.DirectoryServices.AccountManagement namespace.
Of course, depending on your need, you might want to specify other properties on that "query-by-example" user principal you create:
DisplayName (typically: first name + space + last name)
SAM Account Name - your Windows/AD account name
User Principal Name - your "username#yourcompany.com" style name
You can specify any of the properties on the UserPrincipal and use those as "query-by-example" for your PrincipalSearcher.
Given the input of emailAddress (type string) this code will search the LDAP directory for a user with a matching email address and return some information on the user:
string fullName = string.Empty;
string givenName = string.Empty;
string distinguishedName = string.Empty;
string sAMAccountName = string.Empty;
using (var context = new PrincipalContext(ContextType.Domain, "DOMAIN"))
{
using (var searcher = new PrincipalSearcher(new UserPrincipal(context)))
{
foreach (Principal result in searcher.FindAll())
{
var de = result.GetUnderlyingObject() as DirectoryEntry;
if (de.Properties["cn"].Value.ToString().Contains(" "))
{
//var userEntry = new DirectoryUser(de.Properties["sAMAccountName"].Value.ToString());
var currentUserEmail = de.Properties["mail"].Value.ToString().ToLower();
if (currentUserEmail == emailAddress)
{
if (de.Properties["cn"].Value != null)
fullName = de.Properties["cn"].Value.ToString();
if (de.Properties["givenName"].Value != null)
givenName = de.Properties["givenName"].Value.ToString();
if (de.Properties["distinguishedName"].Value != null)
distinguishedName =de.Properties["distinguishedName"].Value.ToString();
if (de.Properties["sAMAccountName"].Value != null)
sAMAccountName = de.Properties["sAMAccountName"].Value.ToString();
}
}
}
}
}
It requires a reference to :
System.DirectoryServices;
System.DirectoryServices.AccountManagement;
One caveat I would like to mention is, directory look up routines can be quite slow. If you have 100,000 users on your domain, this process will take a while to run. WHat I tend to do, is dump the output of a directory search to a database table on a regular basis, and perform any lookups on that table. The frequency of the database dumps will of course depend on your business logic. Sometimes I simply truncate the table before performing a new dump, and in other circumstances, I dump to a 'staging' table, and only apply 'delta' updates to the active directoy record table.
Connect to the directory server, using SSL if possible. Promoting a non-secure connection to a secure connection with the StartTLS extended operation is also possible.
Transmit a SEARCH request to the server that contains the base DN from which the client wishes the search to begin, the scope of the search (base, one-level, or sub-tree), a filter using the information the LDAP client knows that will narrow the search results to the desired user, and the attribute 1.1.
The server will respond with the a SEARCH response containing the number of entries that matched the search request parameters and the distinguished names of each entry that matched.
Transmit a BIND request to the directory server over the secure connection. The BIND request contains a distinguished name and the credentials for the distinguished name
The directory server will verify the credentials and return a BIND response with an integer result code indicating whether the credentials matched those stored in the server database
see also
LDAP: programming practices
LDAP: search practices

Categories

Resources