4

Background:

I've been using UserPrincipal.GetAuthorizationGroups for a while now to check permissions in 2 different applications. They have been working fine for several years. Recently some users have been getting the error mentioned in the title (System.DirectoryServices.AccountManagement.PrincipalOperationException) while others have not. I have a suspicion that it might be related to a new domain controller that was added running on Windows Server 2012 because the problems started the day after it was added. The full error is listed below:

Exception:

System.DirectoryServices.AccountManagement.PrincipalOperationException: An error (1301) occurred while enumerating the groups. The group's SID could not be resolved.

at System.DirectoryServices.AccountManagement.SidList.TranslateSids(String target, IntPtr[] pSids) at System.DirectoryServices.AccountManagement.SidList..ctor(SID_AND_ATTR[] sidAndAttr)

at System.DirectoryServices.AccountManagement.AuthZSet..ctor(Byte[] userSid, NetCred credentials, ContextOptions contextOptions, String flatUserAuthority, StoreCtx userStoreCtx, Object userCtxBase)

at System.DirectoryServices.AccountManagement.ADStoreCtx.GetGroupsMemberOfAZ...p)

at System.DirectoryServices.AccountManagement.UserPrincipal.GetAuthorizationGroups

Question:

How do I fix this?

Community
  • 1
  • 1
skeletank
  • 2,880
  • 5
  • 43
  • 75
  • Is you issue similar to this bug: [GetAuthorizationGroups not returning SG's even though LDAP queries returns appropriate result](http://connect.microsoft.com/VisualStudio/feedback/details/756007/getauthorizationgroups-not-returning-sgs-even-though-ldap-queries-returns-appropriate-result#details)? – Alex Filipovici May 02 '13 at 15:29
  • Yep, except I'm not sure how "Microsoft Endpoint Protection" updates are involved. – skeletank May 02 '13 at 15:39

3 Answers3

5

I've found an alternative using DirectorySearcher:

var allDomains = Forest.GetCurrentForest().Domains.Cast<Domain>();

var allSearcher = allDomains.Select(domain =>
    {
      DirectorySearcher searcher = new DirectorySearcher(
        new DirectoryEntry("LDAP://" + domain.Name));

      searcher.Filter = String.Format(
        "(&(&(objectCategory=person)(objectClass=user)(userPrincipalName=*{0}*)))", 
        "Current User Login Name");

      return searcher;
    }
);

var directoryEntriesFound = 
allSearcher.SelectMany(searcher => 
                        searcher.FindAll()
                          .Cast<SearchResult>()
                          .Select(result => result.GetDirectoryEntry()));

var memberOf = directoryEntriesFound.Select(entry =>
    {
      using (entry)
      {
        return new
        {
          Name = entry.Name,
          GroupName = ((object[])entry.Properties["MemberOf"].Value)
                            .Select(obj => obj.ToString())
        };
      }
    }
);

foreach (var user in memberOf)
{
    foreach (var groupName in user.GroupName)
    {
      if (groupName.Contains("Group to Find"))
      {
        // Do something if the user is in that group
      }
    }
}
skeletank
  • 2,880
  • 5
  • 43
  • 75
  • I thought this solved my problem but when the user in question only belongs to 1 group, this throws: Unable to cast object of type 'System.String' to type 'System.Object[]' – Ju66ernaut Dec 16 '14 at 20:17
  • @skeletank would you happen to know how to deal with this instance? – Ju66ernaut Dec 16 '14 at 21:24
  • @Chris What line does it fail on? – skeletank Dec 17 '14 at 16:40
  • @skeletank When it tries to iterate through the groupName in user.GroupName and actually executes the memberOf query. It works fine for users with more than 1 group but if they only have 1 group it breaks. I have implemented a try catch to work around this, but I am wondering if I can just use this nice code block you have provided with some minor tweaks? Thanks – Ju66ernaut Dec 17 '14 at 17:41
  • @Chris Why don't you use an `if` statement along with a type check such as `entry.Properties["MemberOf"].Value.GetType() == typeof(string)` before you cast the object? – skeletank Dec 17 '14 at 19:14
  • This doesn't get the nested groups though. – wilsjd May 13 '16 at 00:19
0

I had same exception. If someone don't wanna used "LDAP", use this code. Cause I'm had nested groups, I'm used GetMembers(true) and it's little bit longer in time than GetMembers().

or download fix from here like said @Tilo: http://support.microsoft.com/kb/2830145

public bool IsMember(UserPrincipal user, string groupName)
{

            try
            {
                var context = new PrincipalContext(ContextType.Domain, Environment.UserDomainName);
                var group = GroupPrincipal.FindByIdentity(context, groupName);
                if (group == null)
                {
                    //Not exist
                }
                else
                {
                    if (group.GetMembers(true).Any(member => user.SamAccountName.ToLower() == member.SamAccountName.ToLower()))
                    {
                        return true;
                    }
                }
            }
            catch (Exception exception)
            {
                   //exception
            }

            return false;
    }
Nazarii Iaremii
  • 133
  • 3
  • 8