{"id":262,"date":"2011-05-25T12:01:27","date_gmt":"2011-05-25T10:01:27","guid":{"rendered":"http:\/\/hen.co.za\/blog\/?p=262"},"modified":"2011-05-25T12:01:27","modified_gmt":"2011-05-25T10:01:27","slug":"check-if-user-is-in-ad-group","status":"publish","type":"post","link":"https:\/\/hen.co.za\/blog\/2011\/05\/check-if-user-is-in-ad-group\/","title":{"rendered":"Check if user is in AD group"},"content":{"rendered":"<p>This is an action that often is required when you want to make sure a user account may access some resource only if they are part of some AD (OU) group. There are other ways to do this &#8211; if fact it is a lot easier if you use newer versions on the .Net framework (like 3.5 and later) but I had to create something that will still work with the 2.0 framework &#8211; thanks to some older 2003 servers that I have to manage.<\/p>\n<p>I&#8217;m not going to explain too much details on how it works internally &#8211; the simple explanation is that I take the user account and loop through the list of groups the user is a &#8216;memberOf&#8217;. One tricky thing is to also cater for cross domain accounts\/groups &#8211; like when you have a dev domain that also have groups but the user account is part of the live domain &#8211; or some combination like it.<\/p>\n<h2><span style=\"color: #800000;\">A solution<\/span><\/h2>\n<p>The solution is a single helper class with one public method &#8211; IsUserInGroup(string userName, string groupName). Creating an instance of a class with one method is a bit of a waste so the class is a simple static class.<\/p>\n<blockquote><p><span style=\"color: #0000ff;\">public static class DirectoryServicesHelper<\/span><br \/>\n{<\/p>\n<p style=\"padding-left: 30px;\"><span style=\"color: #0000ff;\">private static bool<\/span> useDomainName = false;<\/p>\n<p style=\"padding-left: 30px;\"><span style=\"color: #0000ff;\">public static bool<\/span> IsUserInGroup(<span style=\"color: #0000ff;\">string <\/span>userName, <span style=\"color: #0000ff;\">string <\/span>groupName)<br \/>\n{<\/p>\n<p style=\"padding-left: 60px;\">useDomainName = userName.Contains(&#8220;\\\\&#8221;) || groupName.Contains(&#8220;\\\\&#8221;);<br \/>\n<span style=\"color: #0000ff;\">List<\/span>&lt;<span style=\"color: #0000ff;\">string<\/span>&gt; userGroups = GetGroupsForUser(userName);<br \/>\n<span style=\"color: #0000ff;\">if <\/span>(userGroups.Contains(groupName.ToLower()))<\/p>\n<p style=\"padding-left: 90px;\"><span style=\"color: #0000ff;\">return true<\/span>;<\/p>\n<p style=\"padding-left: 60px;\"><span style=\"color: #0000ff;\">return false<\/span>;<\/p>\n<p style=\"padding-left: 30px;\">}<\/p>\n<\/blockquote>\n<p>The &#8216;useDomainName&#8217; variable is there simply to indicate to other methods if they must cater for domain level details or not. Most of the rest of the code is inside the private &#8216;GetGroupsForUser&#8217; method.<\/p>\n<blockquote><p><span style=\"color: #0000ff;\">private static List<\/span>&lt;<span style=\"color: #0000ff;\">string<\/span>&gt; GetGroupsForUser(<span style=\"color: #0000ff;\">string <\/span>pstrUser)<br \/>\n{<\/p>\n<p style=\"padding-left: 30px;\"><span style=\"color: #0000ff;\">List<\/span>&lt;<span style=\"color: #0000ff;\">string<\/span>&gt; lstGroups = <span style=\"color: #0000ff;\">new List<\/span>&lt;<span style=\"color: #0000ff;\">string<\/span>&gt;();<\/p>\n<p style=\"padding-left: 30px;\"><span style=\"color: #0000ff;\">string <\/span>domain = System.DirectoryServices.ActiveDirectory.<span style=\"color: #0000ff;\">Domain<\/span>.GetCurrentDomain().Name;<br \/>\n<span style=\"color: #0000ff;\">DirectoryEntry <\/span>rootEntry;<br \/>\n<span style=\"color: #0000ff;\">if <\/span>(useDomainName &amp;&amp; pstrUser.Contains(&#8220;\\\\&#8221;))<br \/>\n{<\/p>\n<p style=\"padding-left: 60px;\">domain = pstrUser.Substring(0, pstrUser.IndexOf(&#8220;\\\\&#8221;));<br \/>\npstrUser = pstrUser.Substring(pstrUser.IndexOf(&#8220;\\\\&#8221;) + 1);<\/p>\n<p style=\"padding-left: 30px;\">}<br \/>\nrootEntry = <span style=\"color: #0000ff;\">new DirectoryEntry<\/span>(&#8220;LDAP:\/\/&#8221; + domain);<\/p>\n<p style=\"padding-left: 30px;\"><span style=\"color: #0000ff;\">using <\/span>(<span style=\"color: #0000ff;\">DirectorySearcher <\/span>searcher = <span style=\"color: #0000ff;\">new DirectorySearcher<\/span>(rootEntry, &#8220;objectCategory=User&#8221;))<br \/>\n{<\/p>\n<p style=\"padding-left: 60px;\">searcher.Filter = <span style=\"color: #0000ff;\">string<\/span>.Format(&#8220;(SAMAccountName={0})&#8221;, pstrUser);<br \/>\n<span style=\"color: #0000ff;\">SearchResult <\/span>objSR = searcher.FindOne();<br \/>\n<span style=\"color: #0000ff;\">if <\/span>(objSR != <span style=\"color: #0000ff;\">null<\/span>)<br \/>\n{<\/p>\n<p style=\"padding-left: 90px;\"><span style=\"color: #0000ff;\">using <\/span>(<span style=\"color: #0000ff;\">DirectoryEntry <\/span>objUser = <span style=\"color: #0000ff;\">new DirectoryEntry<\/span>(objSR.Path))<br \/>\n{<\/p>\n<p style=\"padding-left: 120px;\">System.DirectoryServices.<span style=\"color: #0000ff;\">PropertyCollection <\/span>colProperties = objUser.Properties;<br \/>\n<span style=\"color: #0000ff;\">PropertyValueCollection <\/span>colPropertyValues = colProperties[&#8220;memberOf&#8221;];<br \/>\n<span style=\"color: #0000ff;\">foreach <\/span>(<span style=\"color: #0000ff;\">string <\/span>strGroup in colPropertyValues)<br \/>\n{<\/p>\n<p style=\"padding-left: 150px;\">lstGroups.Add(GetSAMAccountName(strGroup).ToLower());<\/p>\n<p style=\"padding-left: 120px;\">}<\/p>\n<p style=\"padding-left: 90px;\">}<\/p>\n<p style=\"padding-left: 60px;\">}<\/p>\n<p style=\"padding-left: 30px;\">}<br \/>\n<span style=\"color: #0000ff;\">return <\/span>lstGroups;<\/p>\n<p>}<\/p>\n<p><span style=\"color: #0000ff;\">private static string<\/span> GetDomainNameFromDE(<span style=\"color: #0000ff;\">DirectoryEntry <\/span>entry)<br \/>\n{<\/p>\n<p style=\"padding-left: 30px;\"><span style=\"color: #0000ff;\">if <\/span>(entry == <span style=\"color: #0000ff;\">null<\/span>)<\/p>\n<p style=\"padding-left: 60px;\"><span style=\"color: #0000ff;\">return <\/span>&#8220;&#8221;;<\/p>\n<p style=\"padding-left: 30px;\"><span style=\"color: #0000ff;\">else<\/span><br \/>\n{<\/p>\n<p style=\"padding-left: 60px;\"><span style=\"color: #0000ff;\">if <\/span>(entry.SchemaClassName == &#8220;domainDNS&#8221;)<\/p>\n<p style=\"padding-left: 90px;\"><span style=\"color: #0000ff;\">return <\/span>entry.Properties[&#8220;Name&#8221;].Value.ToString();<\/p>\n<p style=\"padding-left: 60px;\"><span style=\"color: #0000ff;\">else if <\/span>(entry.Parent != <span style=\"color: #0000ff;\">null<\/span>)<\/p>\n<p style=\"padding-left: 90px;\"><span style=\"color: #0000ff;\">return <\/span>GetDomainNameFromDE(entry.Parent);<\/p>\n<p style=\"padding-left: 60px;\"><span style=\"color: #0000ff;\">else<\/span><\/p>\n<p style=\"padding-left: 90px;\"><span style=\"color: #0000ff;\">return <\/span>&#8220;&#8221;;<\/p>\n<p style=\"padding-left: 30px;\">}<\/p>\n<p>}<\/p>\n<p><span style=\"color: #0000ff;\">private static string<\/span> GetSAMAccountName(<span style=\"color: #0000ff;\">string <\/span>pstrPath)<br \/>\n{<\/p>\n<p style=\"padding-left: 30px;\"><span style=\"color: #0000ff;\">DirectoryEntry <\/span>objADEntry = <span style=\"color: #0000ff;\">null<\/span>;<br \/>\n<span style=\"color: #0000ff;\">string <\/span>output = &#8220;&#8221;;<br \/>\nobjADEntry = <span style=\"color: #0000ff;\">new DirectoryEntry<\/span>(&#8220;LDAP:\/\/&#8221; + pstrPath);<br \/>\n<span style=\"color: #0000ff;\">if <\/span>(objADEntry != <span style=\"color: #0000ff;\">null<\/span>)<br \/>\n{<\/p>\n<p style=\"padding-left: 60px;\"><span style=\"color: #0000ff;\">if <\/span>(useDomainName)<\/p>\n<p style=\"padding-left: 90px;\">output = GetDomainNameFromDE(objADEntry) + &#8220;\\\\&#8221; + objADEntry.Properties[&#8220;SAMAccountName&#8221;].Value.ToString();<\/p>\n<p style=\"padding-left: 60px;\"><span style=\"color: #0000ff;\">else<\/span><\/p>\n<p style=\"padding-left: 90px;\">output = objADEntry.Properties[&#8220;SAMAccountName&#8221;].Value.ToString();<\/p>\n<p style=\"padding-left: 30px;\">}<br \/>\n<span style=\"color: #0000ff;\">return <\/span>output;<\/p>\n<p>}<\/p><\/blockquote>\n<h2><span style=\"color: #800000;\">Summary<\/span><\/h2>\n<p>I&#8217;ve excluded any error checking to make the code simpler to read. For a real utility class you need to add it since AD is an unmanaged resource (as far as .Net goes) and it can throw COM+ errors as well.<\/p>\n<p>With this little helper class you can simply pass it a user and group name and it will return a true or false if the user is part of the group. I&#8217;ve tested it with no domain details, partial domain details, mixed domains etc. Hopefully it can help someone else as well.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is an action that often is required when you want to make sure a user account may access some resource only if they are part of some AD (OU) group. There are other ways to do this &#8211; if &hellip;<\/p>\n<p class=\"read-more\"><a href=\"https:\/\/hen.co.za\/blog\/2011\/05\/check-if-user-is-in-ad-group\/\">Read more &raquo;<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[7,27,8,9,303],"class_list":["post-262","post","type-post","status-publish","format-standard","hentry","category-development","tag-net","tag-active-directory","tag-c","tag-code","tag-development"],"_links":{"self":[{"href":"https:\/\/hen.co.za\/blog\/wp-json\/wp\/v2\/posts\/262","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hen.co.za\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/hen.co.za\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/hen.co.za\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/hen.co.za\/blog\/wp-json\/wp\/v2\/comments?post=262"}],"version-history":[{"count":9,"href":"https:\/\/hen.co.za\/blog\/wp-json\/wp\/v2\/posts\/262\/revisions"}],"predecessor-version":[{"id":271,"href":"https:\/\/hen.co.za\/blog\/wp-json\/wp\/v2\/posts\/262\/revisions\/271"}],"wp:attachment":[{"href":"https:\/\/hen.co.za\/blog\/wp-json\/wp\/v2\/media?parent=262"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hen.co.za\/blog\/wp-json\/wp\/v2\/categories?post=262"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hen.co.za\/blog\/wp-json\/wp\/v2\/tags?post=262"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}