PowerShell – Get all nested groups for a user in Active Directory

Ever needed to get all nested groups a user belongs in Active Directory?


Experienced advanced operations engineer with a demonstrated history of working in the information technology and services industry. Skilled in Windows Server, Azure, Ethical Hacking, Office 365, Exchange, Jenkins, SCCM, Octopus Deploy and PowerShell to name a few. Strong engineering professional with a big passion for knowledge.


  1. criffo

    very nice presentation and good DFS implementation
    I encountered the need as well because of RBAC and external trusts.
    I developped as well a powershell function but based on a BFS and set parameters to take into account the scope search forest, domain, domain trusts forest trusts or explicit domains. I used the.net classes so no need for the RSAT and activedirectory module. I shared the function on my github for anyone who might have some interest as well

  2. Tim Oosterhoff

    What is the need for the line : If($ADObject) ?
    Because if the value is $null the foreach loop does not iterate. That is okay.

      1. Garrett Mattingly

        What Henrik is referring to is that the memberof attribute does not contain the Primary Group. Most often this is Domain Users but it cannot be assumed. Compare output from get-adprincipalgroupmembership versus the contents of the memberof attribute and you can see the discrepancy.

  3. Perica Veljanovski

    This function doesn’t work for Irish people 🙂
    If the DistinguishedName has a ‘ in the person’s name (like O’Reilly) then it will not work.

  4. Gwyn

    I had a similar problem to what Perica describes, but for the names of OUs. Some of our OUs have ‘single quote’ characters in their names. This script does not like them.

    Great job otherwise. Thanks.

  5. Pingback: AD Nested User Permissions – ? About Tech

  6. Ven

    Thank you for this PowerShell script. However, I am not as good as the members that commented here – I would need help in adding the samaccountname in this script for which I need to get a report of all group memberships including nested ones.
    What do I add and where do I add in the script to indicate this is the samaccountname that I am looking for to get a report of group memberships?
    Thank you

    1. Ven

      Sorry. I retried again. I was able to do that. It was so simple. Thank you for putting this one together and sharing this.

  7. Marcos de Oliveira

    Recently I found out about tokenGroups[1][2] attribute, which is way faster than LDAP_MATCHING_RULE_IN_CHAIN[3], so I’m spreading the word:

    To get all AD object groups recursively:
    (Get-ADUser username | Get-ADUser -Properties tokenGroups).tokenGroups.ForEach({
    ($_ | Get-ADGroup).Name

    Or, if you don’t need an ADGroup object, this returns a String instead, but is way faster:
    (Get-ADUser username | Get-ADUser -Properties tokenGroups).tokenGroups.ForEach({

    It’s almost instantaneous in our directory:
    PS C:\windows\System32> (Get-ADUser -Filter *).Count
    PS C:\windows\System32> (Get-ADGroup -filter *).Count
    PS C:\windows\System32> (Get-ADComputer -filter *).Count

    Just for reference, here how much time it takes in this instance:

    PS C:\Windows\System32>
    # this returns String objects
    1..10 | % {
    Measure-Command {
    (Get-ADUser marcossantos | Get-ADUser -Properties tokenGroups).tokenGroups.ForEach({$_.Translate([System.Security.Principal.NTAccount]).Value})
    } | Measure-Object -Average TotalSeconds | select @{l=”Type”;e={“String”}},Average

    # this returns ADGroup objects
    1..10 | % {
    Measure-Command {
    (Get-ADUser marcossantos | Get-ADUser -Properties tokenGroups).tokenGroups.ForEach({($_ | Get-ADGroup).Name})
    } | Measure-Object -Average TotalSeconds | select @{l=”Type”;e={“ADGroup”}},Average

    Type Average
    —- ——-
    String 0.01926139
    ADGroup 0.28920375

    One downside of this approach is that it does not retrieve distribution groups.


Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.