locked
GetAuthorizationGroups() fails with NoMatchingPrincipalException RRS feed

  • Question

  • Hello

    I am trying to enumerate all the authorization groups for a specific user in a small console app. I am able to display a whole bunch of groups but at some point it throws a NoMatchingPrincipalException. Any ideas? Here is the code that you could just copy + paste and just change the domain name and user name to match your environment:

    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Text;  
    using System.DirectoryServices.AccountManagement;  
     
    namespace GetRolesForUserSpike  
    {  
        class Program  
        {  
            static void Main(string[] args)  
            {  
                var username = "Gabriel";  
                using (PrincipalContext context = new PrincipalContext(ContextType.Domain, "MYDOMAIN"))  
                {  
                    UserPrincipal p = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, username);  
                    var groups = p.GetAuthorizationGroups();  
                    foreach (var group in groups)  
                    {  
                        Console.WriteLine(group);  
                    }  
                }  
                Console.ReadKey();  
            }  
        }  

    Give a man a fish and you feed him for a day. Teach a man to fish and you feed him a lifetime
    Friday, January 23, 2009 8:17 AM

Answers

  •  

    Hello,

    Your code works fine at my side.   The “NoMatchingPrincipalException” is thrown when no matching prinicipal object could be found with the specified parameters.

    You can consider debugging the codes.  In each line of codes, you can check the return value of the methods to troubleshoot the issue step by step, especially the value of UserPrincipal p.  

            static void Main(string[] args)

            {

                var username = "username";

                using (PrincipalContext context = new PrincipalContext(ContextType.Domain, "DOMAIN"))

                {

                    UserPrincipal p = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, username);

     

                    // please check whether UserPrincipal p is correct

                    Console.WriteLine(p.Name);

     

                    var groups = p.GetAuthorizationGroups();

                    foreach (var group in groups)

                    {

                        Console.WriteLine(group);

                    }

                }

                Console.ReadKey();  

            }

     

    Best Regards,
    Lingzhi


    Please remember to mark the replies as answers if they help and unmark them if they provide no help. http://forums.msdn.microsoft.com/en-US/csharpide/thread/8e9ed0d7-11ff-402a-8489-9b5f05eeb706 http://forums.msdn.microsoft.com/en-US/vssetup/thread/60424309-bd78-4ca2-b618-03c4a16123b6
    Tuesday, January 27, 2009 10:17 AM

All replies

  •  

    Hello,

    Your code works fine at my side.   The “NoMatchingPrincipalException” is thrown when no matching prinicipal object could be found with the specified parameters.

    You can consider debugging the codes.  In each line of codes, you can check the return value of the methods to troubleshoot the issue step by step, especially the value of UserPrincipal p.  

            static void Main(string[] args)

            {

                var username = "username";

                using (PrincipalContext context = new PrincipalContext(ContextType.Domain, "DOMAIN"))

                {

                    UserPrincipal p = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, username);

     

                    // please check whether UserPrincipal p is correct

                    Console.WriteLine(p.Name);

     

                    var groups = p.GetAuthorizationGroups();

                    foreach (var group in groups)

                    {

                        Console.WriteLine(group);

                    }

                }

                Console.ReadKey();  

            }

     

    Best Regards,
    Lingzhi


    Please remember to mark the replies as answers if they help and unmark them if they provide no help. http://forums.msdn.microsoft.com/en-US/csharpide/thread/8e9ed0d7-11ff-402a-8489-9b5f05eeb706 http://forums.msdn.microsoft.com/en-US/vssetup/thread/60424309-bd78-4ca2-b618-03c4a16123b6
    Tuesday, January 27, 2009 10:17 AM
  • Apperently this exception is being thrown when an SID cannot be resolved. AFAIK this makes GetAuthorizationGroups() useless in corporate networks. No seriously, I am sure that it will also fail when you run it on one of your MSFT AD domains. Large companies with several thousands of users with multiple Active Directory domains will also contain obsolete SID's. I cannot possible ask IT to clean up the mess just because our code cannot call GetAuthorizationGroups. It is not even possible to catch the exception and just continue because when this exception is thrown we are done playing.
    Give a man a fish and you feed him for a day. Teach a man to fish and you feed him a lifetime
    Friday, January 30, 2009 7:03 PM
  • using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Text;  
    using System.DirectoryServices;  
     
    namespace GetGroupsForADUser  
    {  
        class Program  
        {  
            static void Main(string[] args)  
            {  
                String username = "Gabriel";  
     
                List<string> userNestedMembership = new List<string>();  
     
                DirectoryEntry domainConnection = new DirectoryEntry();  
                domainConnection.Path = "LDAP://DC=mydomain,DC=local";  
                domainConnection.AuthenticationType = AuthenticationTypes.Secure;  
     
     
                DirectorySearcher samSearcher = new DirectorySearcher();  
     
                samSearcher.SearchRoot = domainConnection;  
                samSearcher.Filter = "(samAccountName=" + username + ")";  
                samSearcher.PropertiesToLoad.Add("displayName");  
     
                SearchResult samResult = samSearcher.FindOne();  
     
                if (samResult != null)  
                {  
                    DirectoryEntry theUser = samResult.GetDirectoryEntry();  
                    theUser.RefreshCache(new string[] { "tokenGroups" });  
     
                    foreach (byte[] resultBytes in theUser.Properties["tokenGroups"])  
                    {  
                        System.Security.Principal.SecurityIdentifier mySID = new System.Security.Principal.SecurityIdentifier(resultBytes, 0);  
     
                        DirectorySearcher sidSearcher = new DirectorySearcher();  
     
                        sidSearcher.SearchRoot = domainConnection;  
                        sidSearcher.Filter = "(objectSid=" + mySID.Value + ")";  
                        sidSearcher.PropertiesToLoad.Add("distinguishedName");  
     
                        SearchResult sidResult = sidSearcher.FindOne();  
     
                        if (sidResult != null)  
                        {  
                            userNestedMembership.Add((string)sidResult.Properties["distinguishedName"][0]);  
                        }  
                    }  
     
                    foreach (string myEntry in userNestedMembership)  
                    {  
                        Console.WriteLine(myEntry);  
                    }  
     
                }  
                else 
                {  
                    Console.WriteLine("The user doesn't exist");  
                }  
     
                Console.ReadKey();  
     
            }  
        }  
    }  
     
    Yes, I'm having the same problem, I ended up dropping down out of the AccountManagement stuff and back into DirectoryServices, which is very unfortunate, I think Microsoft shoudl fix GetAuthorizationGroups to not fail on external SID's.

    Hope that helps, I'll be wrapping it up in a function and using it quite a bit, is annoying tho because I prefer using the new DirectoryContext objects, but falling down to DirectorySearcher stops me from using those.

    Cheers,

    David
    Wednesday, February 4, 2009 6:18 AM
  • Yup, I can confirm that GetAuthorizationGroups will crash if the user is a member of any groups in AD that have SidHistory enabled.  When you enumerate the tokenGroups of that user you will see the SID's from SidHistory, and the SID's of the actual group in your AD Domain.

    If the user is a member of groups that have no SidHistory then you are fine.

    The expected reaction of GetAuthorizationGroups woudl be to ignore group membership of any groups where the SID cannot be resolved, or to search the SidHistory values in the current domain to see if the group is in the current domain, where you would ignore the group if it was found in the current domain (because the user is also a member of the groups actual SID) and add the group in the reply where the name of the group was the SID for those groups that cannot be resolved in the domain, to let stuff know he is a member of another group.

    This is a bug, I suppose Microsoft should fix it.

    Where to log a bug report?

    Cheers,

    David
    Thursday, February 5, 2009 2:43 AM
  • I just got this error with GetAuthorizationGroups(), I'm now swallowing "NoMatchingPrincipalException" exceptions, however I'm sure this isn't an ideal solution.

    This is where a VS/.NET Framework bug can be logged: https://connect.microsoft.com/VisualStudio.

    Monday, March 16, 2009 7:05 AM
  • I also experienced this issue.  This is also reported as a public bug on Connect, I encourage you to go vote on it there to get this issue raised.

    https://connect.microsoft.com/VisualStudio/feedback/details/522539/clr-forum-error-calling-principal-getauthorizationgroups-in-winxp-sp3?wa=wsignin1.0#

    I posted a workaround on that forum, but here it is as well.  I was able to workaround this issue by manually iterating through the PrincipalSearchResult<Principal> returned objects, catching this exception, and continuing on.

     

    PrincipalSearchResult<Principal> groups = user.GetAuthorizationGroups();
    var iterGroup = groups.GetEnumerator();
    using (iterGroup)
    {
        while (iterGroup.MoveNext())
        {
            try
            {
                Principal p = iterGroup.Current;
                Console.WriteLine(p.Name);
            }
            catch (NoMatchingPrincipalException pex)
            {
                continue;
            }
        }
    }

    • Edited by mohlsen Thursday, April 15, 2010 3:21 PM formatting
    • Proposed as answer by mohlsen Thursday, April 15, 2010 3:22 PM
    Thursday, April 15, 2010 3:19 PM