How to know if user exists in AD Group efficiently - c#

In a sharepoint solution I need to get all users from an AD Group, for the time being this AD group can have 30 users, but in the future, we could replace the AD group with one that has 1000 users. and because this code is executed for each user on each request (its a navigation component to show/hide the OneDrive Link), then I need it to be as efficient as possible.
// Get all users from a group recursively.
var context = new System.DirectoryServices.AccountManagement.PrincipalContext(ContextType.Domain);
GroupPrincipal group = new GroupPrincipal(context ,farm.Properties[GlobalNavigationConstants.Keys.GlobalNavigationOneDriveADGroup].ToString());
PrincipalSearchResult<Principal> members = group.GetMembers(true);
var list = members.OfType<UserPrincipal>().ToList();
//Get current user
var loginName = SPContext.Current.Web.CurrentUser.LoginName;
//How to check if loginname is on list efficiently?
How can I do this as fast as possible?

Warning, NOT tested.
var context = new System.DirectoryServices.AccountManagement.PrincipalContext(ContextType.Domain);
GroupPrincipal group = new GroupPrincipal(context,
farm.Properties[GlobalNavigationConstants.Keys.GlobalNavigationOneDriveADGroup].ToString());
UserPrincipal usr = UserPrincipal.FindByIdentity(context,
IdentityType.Sid,
SPContext.Current.Web.CurrentUser.Sid);
var found = usr.IsMemberOf(group);

Related

How to get LDAP nested groups from attribute

I can search the user and find only the groups that the user belongs to. And now i want to return all the groups/roles and assign a user to a specific group/role.
DirectoryEntry and PrincipalContext doesn't work in my case and i have tried that for days.
This is my working code for searching user group/roles which is working fine.
How can i get all the groups/roles?
And Add user to a group/role
Container = “ou=containername,ou=xx,ou=xx,O=xxxxx”
Domain = “mydomain.com”
group = ou=groups,ou=containername,ou=xx,ou=xx,O=xxxx
List<string> roles = new List<string>();
SearchRequest request = new SearchRequest("", "(&(objectClass=person)(mail=myusername))", System.DirectoryServices.Protocols.SearchScope.Subtree);
SearchResponse response = (SearchResponse)con.SendRequest(request);
if (response.Entries.Count == 0)
{
return null;
}
else
{
foreach (SearchResultEntry entry in response.Entries)
{
if (entry.Attributes["member"] != null)
{
roles = (entry.Attributes["member"].GetValues(typeof(string))).ToArray().Select(r => r.ToString()
.Substring(r.ToString().IndexOf("cn=") + 3,
r.ToString().IndexOf(",") - 3))
.ToList();
}
}
}
return roles;
I don't think you're using Active Directory. What tipped me off is that you're getting data from the member attribute of a user. That's not how it works with Active Directory (it would be memberOf).
I'm not entirely sure what you're asking for. Your title mentioned "nested groups", which means when one group is a member of another group. So I assume that would mean that you want to find every group the user is a member of and all groups that those groups are members of, etc. If that's the case, you will really have to find out what type of server you're connecting to before anyone can give you a good answer on that.
But in your question you say "How can i get all the groups/roles?" So does that mean you just want to find every group that exists? To do that, you can just do a new search and use this as the filter:
(objectClass=group)
For adding a user to a group, I think it would be something like this (where userDn is the distinguishedName of the user you want to add, and groupDn is that of the group):
var mod = new DirectoryAttributeModification {
Name = "member",
Operation = DirectoryAttributeOperation.Add
}
mod.Add(userDn);
var response = (ModifyResponse) connectionObject.SendRequest(
new ModifyRequest {
DistinguishedName = groupDn,
Modifications = { mod }
}
);
But I've never actually used LdapConnection, so you might need to tweak it.
By default, the ADLDS or AD MemberOf (User object) Member (Group object) attribute is not retrieved.
Example Solution for User
SearchRequest request = new SearchRequest("", "(&(objectClass=user)(mail=myusername))", System.DirectoryServices.Protocols.SearchScope.Subtree);
request.Attributes.Add("memberOf");
or Group
SearchRequest request = new SearchRequest("", "(&(objectClass=group))", System.DirectoryServices.Protocols.SearchScope.Subtree);
request.Attributes.Add("member");
Default LDAP Filters and Attributes for Users, Groups and Containers

Get Primary Group From UserPrincipal C#

I want to locate the Primary Group from the code below
I can get all the Groups for a user, but which one is the primary group?
string primaryGroupName = String.Empty;
using (PrincipalContext context = new PrincipalContext(ContextType.Domain))
{
using (UserPrincipal user = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, "userName"))
{
foreach (Principal p in user.GetGroups())
{
WriteLog("PrimaryGroup Name(s)???:");
WriteLog(p.Name);
primaryGroupName = p.Name;
}
}
}
Whats returned from the code above is...
Domain Users
Administrators
Schema Admins
Enterprise Admins
Domain Admins
..and a few more
What is the Primary Group?
You have the right idea: The primaryGroupID holds the RID (Relative Identifier) of the group that is the primary group. The RID is the last set of numbers in the SID. The rest of the SID identifies the domain. So you can figure out the SID of the group using the SID of the user and the primaryGroupID.
I wrote a couple articles about this. One called What makes a member a member?, with a section describing the primary group. But also an article called Finding all of a user’s groups where I shared some code to find the primary group. I have found that using DirectoryEntry directly is always faster than using UserPrincipal/GroupPrincipal, so that's what my examples use:
Here is the method:
private static string GetUserPrimaryGroup(DirectoryEntry de) {
de.RefreshCache(new[] {"primaryGroupID", "objectSid"});
//Get the user's SID as a string
var sid = new SecurityIdentifier((byte[])de.Properties["objectSid"].Value, 0).ToString();
//Replace the RID portion of the user's SID with the primaryGroupId
//so we're left with the group's SID
sid = sid.Remove(sid.LastIndexOf("-", StringComparison.Ordinal) + 1);
sid = sid + de.Properties["primaryGroupId"].Value;
//Find the group by its SID
var group = new DirectoryEntry($"LDAP://<SID={sid}>");
group.RefreshCache(new [] {"cn"});
return group.Properties["cn"].Value as string;
}
To use that from your code, you would do this:
var primaryGroupName = GetUserPrimaryGroup((DirectoryEntry) user.GetUnderlyingObject());
That method just returns the name of the group, but you can modify it as you need.
All that said, 513 is always the RID of the built-in Domain Users group.

Get AD group membership for the current user on another domain

I have a bit of code to get all of the AD groups for the user currently logged in:
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, Environment.UserDomainName);
// find a user
UserPrincipal adUser = UserPrincipal.FindByIdentity(ctx, user);
if (adUser == null)
{
Logger.Error("Could not find related Active Directory user");
return;
}
GetUserDetailsFromGroupMembership(adUser.GetGroups().Select(g => g.Name));
This will get all the groups the current user is part of on its registered domain. My username is part of the "EUR" domain, but I also have memberships on the "USA" domain. How do I also query groups in the other domains?
GetGroups() gets all the groups from domains in the same forest, so I have to assume that your two domains are not in the same forest, but are trusted by each other.
I don't know of a way to do this with the AccountManagement namespace, but this is how you would do it with DirectorySearcher.
When accounts get added to groups on an external, trusted domain, they show up as Foreign Security Principal objects, which contain the SID of the account. So that's what you have to search for. You already have the account in the adUser variable, so I'm using adUser.Sid here.
I assume you will always be searching the one other domain, so you can hard code the distinguishedName of the other domain in the first line.
var otherDomainDN = "DC=usa,domain,DC=com";
var ds = new DirectorySearcher(new DirectoryEntry($"LDAP://{otherDomainDN}"),
$"(&(objectClass=group)(member=CN={adUser.Sid},CN=ForeignSecurityPrincipals,{otherDomainDN}))");
ds.PropertiesToLoad.Add("cn");
var otherDomainGroups = new List<string>();
foreach (SearchResult g in ds.FindAll()) {
otherDomainGroups.Add(g.Properties["cn"][0].ToString());
}
After this, otherDomainGroups will be a list of the names of the other groups.

Get all the parent AD groups a user belongs to

I want to get all the Active Directory groups in which a particular user is a member.
I do have the script to get all the immediate AD groups for a user (see codes below).
However, how do I get all the parent groups for each of the immediate AD groups the user belongs to?
e.g. I am directly part of the AD group called IT Team Managers. This group is member of a parent group called IT Team National etc. How do I get this parent group from my code?
Thanks so much in advance!
DirectorySearcher ouSearch = new DirectorySearcher(entry);
ouSearch.Filter = "(&(objectClass=User)(sAMAccountName=" + username + "))";
//ouSearch.PropertiesToLoad.Add("samAccountName");
ouSearch.PropertiesToLoad.Add("memberOf");
ouSearch.SearchScope = SearchScope.Subtree;
SearchResult allOUS = ouSearch.FindOne();
//foreach (string g in allOUS.Properties["memberOf"])
{
equalsIndex = g.IndexOf("=", 1);
commaIndex = g.IndexOf(",", 1);
if (equalsIndex == -1)
{
return null;
}
groupNames.Append(g.Substring((equalsIndex + 1), (commaIndex - equalsIndex) - 1));
groupNames.Append(",");
}
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
PrincipalContext ctx = new PrincipalContext(ContextType.Domain);
// find a user
UserPrincipal user = UserPrincipal.FindByIdentity(ctx, "SomeUserName");
if(user != null)
{
// get the "authorization groups" the user is a member of - recursively
var authGroups = user.GetAuthorizationGroups();
// iterate over groups
foreach(Principal p in authGroups)
{
// do something with groups ....
}
}
The new S.DS.AM makes it really easy to play around with users and groups in AD!

How to get SID of a group once i get groups of a user in Active Directory?

I am using DirectorySearcher to get groups of a User in ActiveDirectory.
My Question is how to get SID associated with each group once i get user groups using "memberOf"?
I am working in .NETFramework 2.0 Environment.
DirectoryEntry entry = new DirectoryEntry(string.Format("LDAP://{0}", sUserDomain));
DirectorySearcher mySearcher = new DirectorySearcher(entry);
mySearcher.Filter = string.Format("(&(objectClass=user) (cn= {0}))", ui.DisplayName.ToString());
mySearcher.PropertiesToLoad.Add("memberOf");
SearchResult searchresult = mySearcher.FindOne();
There is no way to do it in one single LDAP search because memberOf returns a distinguish name. You have to do another bind to get the objectSid attribute from the group object. Here is the code.
DirectoryEntry entry = new DirectoryEntry(string.Format("LDAP://{0}", sUserDomain));
DirectorySearcher mySearcher = new DirectorySearcher(entry);
mySearcher.Filter = string.Format("(&(objectClass=user) (cn= {0}))", ui.DisplayName.ToString());
mySearcher.PropertiesToLoad.Add("memberOf");
SearchResult searchresult = mySearcher.FindOne();
foreach (string dn in searchresult.Properties["memberOf"])
{
DirectoryEntry group = new DirectoryEntry(string.Format("LDAP://{0}/{1}", sUserDomain, dn));
SecurityIdentifier sid = new SecurityIdentifier(group.Properties["objectSid"][0] as byte[], 0);
Console.Out.WriteLine(sid.Value);
}
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:
// define context for current domain
using(PrincipalContext ctx = new PrincipalContext(ContextType.Domain))
{
// find user
UserPrincipal user = UserPrincipal.FindByIdentity(ctx, "YourNameHere");
if (user != null)
{
// get groups the user is a member of
var groups = current.GetGroups();
// iterate over all those groups
foreach(var group in groups)
{
// fetch the SID for each group
var sid = group.Sid;
}
}
}
The new S.DS.AM makes it really easy to play around with users and groups in AD!
Have a look at his article:
Retrieving user SID using DirectoryEntry and DirectorySearcher
This gives you a full working example for retrieving the SID.

Categories

Resources