Managing role assignments in Microsoft 365 is a critical administrative task—but it’s equally important to know which administrators are licensed and actively assigned to critical roles like Global Administrator, Teams Administrator, and more.
In this article, we’ll walk you through a Graph PowerShell script that reliably fetches licensed administrators along with their roles, user details, and sign-in status—using only Microsoft Graph v1.0.
# Connect to Microsoft Graph
Connect-MgGraph -Scopes "Directory.Read.All", "User.Read.All"
# Step 1: Get all activated directory roles
$roles = (Invoke-MgGraphRequest -Method GET -Uri "v1.0/directoryRoles").value
# Step 2: Prepare user-role map
$licensedAdminsMap = @{}
foreach ($role in $roles) {
$roleId = $role.id
$roleName = $role.displayName
Write-Host "Checking members for role: $roleName" -ForegroundColor Yellow
# Step 3: Call /directoryRoles/{id}/members to get members of this role
try {
$membersResponse = Invoke-MgGraphRequest -Method GET -Uri "v1.0/directoryRoles/$roleId/members"
$members = $membersResponse.value
} catch {
Write-Warning "Could not retrieve members for role $roleName"
continue
}
foreach ($member in $members) {
if (-not $member.userPrincipalName) { continue } # Skip non-user objects
# Step 4: Check if user has license
try {
$licenseInfo = Invoke-MgGraphRequest -Method GET -Uri "v1.0/users/$($member.id)/licenseDetails"
} catch {
Write-Warning "License lookup failed for: $($member.displayName)"
continue
}
if ($licenseInfo.value.Count -eq 0) {
continue # Skip unlicensed users
}
$upn = $member.userPrincipalName
if (-not $licensedAdminsMap.ContainsKey($upn)) {
$licensedAdminsMap[$upn] = @{
DisplayName = $member.displayName
UserPrincipalName= $upn
LicenseStatus = "Licensed"
Roles = @($roleName)
JobTitle = $member.jobTitle
}
} else {
$licensedAdminsMap[$upn].Roles += $roleName
}
}
}
# Step 5: Format output
$licensedAdmins = $licensedAdminsMap.Values | ForEach-Object {
[PSCustomObject]@{
"Admin Name" = $_.DisplayName
"User Principal Name"= $_.UserPrincipalName
"License Status" = $_.LicenseStatus
"Job Title" = $_.JobTitle
"Admin Roles" = ($_.Roles -join ", ")
}
}
# Step 6: Display result
$licensedAdmins | Format-Table -AutoSize
The output is formatted into a clean table for review or export.
You can easily extend this script to:
$licensedAdmins | Export-Csv -Path "LicensedAdminsReport.csv" -NoTypeInformation -Encoding UTF8
Get-MgUser -ExpandProperty signInActivity.
Modify the filter to:
$filter = "category eq 'Policy' and activityDateTime ge $startTime"
Error | Cause | Solution |
userPrincipalName not found | Member is not a user (e.g., service principal) | Skip the object (already handled in script) |
License lookup failed | User account is inaccessible or license details API fails | Wrapped in try/catch, script continues |
403 Forbidden or 401 Unauthorized | Insufficient Graph permissions | Run Connect-MgGraph with Directory.Read.All and User.Read.All |
No output / empty result | No roles assigned or users not licensed | Validate via Entra admin center and assign proper test data |
This script offers a reliable, v1.0-compliant, and production-ready method to report on licensed administrators in Microsoft 365. It’s particularly useful for organizations that want to tighten security, ensure role compliance, and maintain license efficiency.
Because it avoids the beta endpoint, you can deploy it confidently in production environments without extra installations.
© m365corner.com. All Rights Reserved. Design by HTML Codex