Fetch All Admin Role Users in Microsoft 365 Using Graph PowerShell

Managing admin role assignments is critical in Microsoft 365 for maintaining security, compliance, and operational oversight. This article walks you through a powerful Graph PowerShell script that lists all users assigned to any administrative role, including their name, user principal name, sign-in status, and admin roles.


The Script: List All Admin Role Users in Microsoft 365

# Connect to Microsoft Graph with the required scopes
Connect-MgGraph -Scopes "RoleManagement.Read.Directory", "Directory.Read.All", "User.Read.All"
                                
# Get all activated directory roles (e.g., Global Admin, Helpdesk Admin)
$activatedRoles = Get-MgDirectoryRole -All
                                
# Hashtable to store users and their roles
$adminUserMap = @{}
                                
foreach ($role in $activatedRoles) {
    try {
        # Get members of the role (could include users, groups, service principals)
        $members = Get-MgDirectoryRoleMember -DirectoryRoleId $role.Id -All
                                        
        foreach ($member in $members) {
            # Process only user objects
            if ($member.AdditionalProperties.'@odata.type' -eq "#microsoft.graph.user") {
                $userId = $member.Id
                                                
                # Fetch detailed user info only once
                if (-not $adminUserMap.ContainsKey($userId)) {
                $user = Get-MgUser -UserId $userId -Property DisplayName, UserPrincipalName, AccountEnabled
                                                
                $adminUserMap[$userId] = [PSCustomObject]@{
                'Admin Name'          = $user.DisplayName
                'User Principal Name' = $user.UserPrincipalName
                'Sign In Status'      = if ($user.AccountEnabled) { "Enabled" } else { "Disabled" }
                'Admin Roles'         = $role.DisplayName
                }
            } else {
                # Append additional role to existing user
                $adminUserMap[$userId].'Admin Roles' += ", $($role.DisplayName)"
            }
            }
        }
    } catch {
            Write-Warning "Error while processing role '$($role.DisplayName)': $_"
    }
}

# Output the result
$adminUserMap.Values | Sort-Object 'Admin Name' | Format-Table -AutoSize
                            

How the Script Works

Here’s a step-by-step breakdown of the script’s logic:

  1. Connects to Microsoft Graph with necessary delegated permissions:
    • RoleManagement.Read.Directory
    • Directory.Read.All
    • User.Read.All
  2. Retrieves all active directory roles using Get-MgDirectoryRole.
  3. Iterates through each active role and calls:
    • Get-MgDirectoryRoleMember to fetch the members assigned.
  4. Filters only those members who are actual users (ignoring service principals, groups, etc.).
  5. Fetches each user’s DisplayName, UserPrincipalName, and AccountEnabled status.
  6. Maintains a hashtable to:
    • Avoid duplicate calls for the same user.
    • Combine multiple admin roles assigned to a single user.
  7. Finally, displays a clean tabular report of all admin users.

Further Enhancements

You can enhance the script to include additional metadata such as:

  • Last Sign-In Date
  • -Property SignInActivity

    and expand using:

    $user.SignInActivity.LastSignInDateTime
  • Job Title, Department, or Country
  • by including additional properties in the Get-MgUser call.

  • CSV Export for reporting:
  • $adminUserMap.Values | Export-Csv -Path "AdminRoleUsers.csv" -NoTypeInformation
  • Filter by specific roles, e.g., only Global Admins:
  • if ($role.DisplayName -eq "Global Administrator")

Possible Errors & Solutions

Error Message Cause Solution
No activated roles found Roles not yet activated in the tenant Activate roles via Azure Portal or PowerShell
Get-MgDirectoryRoleMember : Access denied Missing permissions or role limitations Ensure required scopes and sufficient privileges
@odata.type not accessible The default object does not expose @odata.type directly Access using .AdditionalProperties.'@odata.type'
Cannot bind argument to parameter because it is null Invalid or null $userId due to non-user objects Validate @odata.type before calling Get-MgUser
Empty response No users currently assigned to any active roles Confirm assignments through Entra admin center or Graph Explorer

Frequently Asked Questions

  • Why does Get-MgDirectoryRoleMember return no results for some roles?
  • Some roles in Entra ID (Azure AD) may not have any users assigned to them. If a role has no members, the cmdlet will return an empty result set for that role.

  • How do I list users assigned to multiple roles simultaneously?
  • You’ll need to loop through each role ID using Get-MgDirectoryRole and retrieve members individually using Get-MgDirectoryRoleMember. There’s no direct cmdlet to retrieve all role-to-user mappings in one call.

  • Can I use the Display Name of the role directly to fetch members?
  • No, Get-MgDirectoryRoleMember requires the Id (GUID) of the role. You must first retrieve the role using Get-MgDirectoryRole -Filter "displayName eq 'Global Administrator'" and then use its Id.

  • Why is the Global Administrator role sometimes missing from the list?
  • Ensure that the role has been activated in the tenant. Some roles, especially privileged ones like Global Administrator or Privileged Role Administrator, may not appear in Get-MgDirectoryRole until they are assigned to at least one user.

Use Cases

This script is extremely useful for:

  • Security Audits: Know who has elevated access in your tenant.
  • Access Reviews: Periodically review and revoke unneeded roles.
  • IT Automation: Integrate into compliance reporting workflows.
  • Exportable Reporting: Provide auditors or stakeholders with clean admin user reports.
  • Role Reconciliation: Cross-verify Graph-based data with Entra ID Portal.

✅ Role Membership Is Not Always Synced Immediately
When assigning roles via the Microsoft 365 admin center or Graph API, changes might take a few minutes to reflect in Get-MgDirectoryRoleMember. If your query returns empty results after an assignment, wait a short while before rechecking.
✅ Some Directory Roles May Have No Members
Not all available roles in Azure AD have assigned members. It’s good practice to script checks that skip empty roles when generating role assignment reports to reduce clutter and improve report clarity.

Conclusion

With this Graph PowerShell script, Microsoft 365 administrators can easily monitor and audit all users who have been assigned privileged roles within the tenant. It provides clear visibility into who has access to critical functions and makes it simple to report, review, and respond.

By extending the script with sign-in insights or job role data, you can create a complete admin governance solution. Be sure to run this script periodically to maintain security hygiene in your Microsoft 365 environment.


Graph PowerShell Explorer Widget

20 Graph PowerShell cmdlets with easily accessible "working" examples.


Permission Required

Example:


                


                


                

© m365corner.com. All Rights Reserved. Design by HTML Codex