The behaviour you are seeing would appear to be by design, see Which Groups Does WindowsIdentity.Groups Return?
To summarise
Under the covers, WindowsIdentity populates the groups collection by querying Windows for information on the groups that the user token is a member of. However, before returning this list, the Groups property filters out some of the returned groups.
Specifically, any groups which were on the token for deny-only will not be returned in the Groups collection. Similarly, a group which is the SE_GROUP_LOGON_ID will not be returned.
...If you want to retrieve all of the groups however, there's not an easy built-in way for you to do this. Instead, you'll have to P/Invoke to the GetTokenInformation API to retrieve the groups yourself.
public static void Main()
{
using (WindowsIdentity currentIdentity = WindowsIdentity.GetCurrent())
{
var groups = // Get all of the groups from our account, and translate them from IdentityReferences to NTAccounts
from groupIdentity in currentIdentity.Groups
where groupIdentity.IsValidTargetType(typeof(NTAccount))
select groupIdentity.Translate(typeof(NTAccount)) as NTAccount into ntAccounts
// Sort the NTAccounts by their account name
let domainName = ntAccounts.GetDomainName()
let groupName = ntAccounts.GetAccountName()
orderby domainName
// Group the sorted accounts by the domain they belong to, and sort the grouped groups by domain name
group ntAccounts by domainName into domainGroups
orderby domainGroups.Key
select domainGroups;
foreach (var domainGroups in groups)
{
Console.WriteLine("Groups from domain: {0}", domainGroups.Key);
foreach (var group in domainGroups)
{
Console.WriteLine(" {0}", group.GetAccountName());
}
}
}
}
private static string GetDomainName(this NTAccount account)
{
string[] split = account.Value.Split('\\');
return split.Length == 1 ? String.Empty : split[0];
}
private static string GetAccountName(this NTAccount account)
{
string[] split = account.Value.Split('\\');
return split[split.Length - 1];
}