Knowing who has been recently granted administrative access in your Microsoft 365 tenant is a critical part of security oversight and change tracking. Newly created admin accounts—whether intentional or suspicious—must be closely monitored to avoid unauthorized privilege escalation.
This article walks you through a Graph PowerShell script that lists all users with admin roles who were created in the last 90 days, along with key details like their sign-in status and assigned roles.
# Connect to Microsoft Graph
Connect-MgGraph -Scopes "RoleManagement.Read.Directory", "Directory.Read.All", "User.Read.All"
# Set cutoff date to 90 days ago
$cutoffDate = (Get-Date).AddDays(-90)
# Get all activated directory roles
$activeRoles = Get-MgDirectoryRole -All
# Hashtable to collect recently created admins
$recentAdmins = @{}
foreach ($role in $activeRoles) {
try {
# Get members of the role
$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 user details including creation and account status
$user = Get-MgUser -UserId $userId -Property DisplayName, UserPrincipalName, AccountEnabled, CreatedDateTime
if ($user.CreatedDateTime -ge $cutoffDate) {
if ($recentAdmins.ContainsKey($userId)) {
# Append additional admin role
$recentAdmins[$userId].'Admin Roles' += ", $($role.DisplayName)"
} else {
$recentAdmins[$userId] = [PSCustomObject]@{
'Admin Name' = $user.DisplayName
'UserPrincipalName' = $user.UserPrincipalName
'SignIn Status' = if ($user.AccountEnabled) { "Enabled" } else { "Disabled" }
'Admin Roles' = $role.DisplayName
}
}
}
}
}
} catch {
Write-Warning "Error processing role '$($role.DisplayName)': $_"
}
}
# Output the result
if ($recentAdmins.Count -eq 0) {
Write-Host "No administrators created in the past 90 days were found." -ForegroundColor Yellow
} else {
$recentAdmins.Values | Sort-Object 'Admin Name' | Format-Table -AutoSize
}
Here’s what this script does step by step:
It authenticates using delegated permissions:
Using (Get-Date).AddDays(-90), it calculates a date threshold to compare user creation dates.
Uses Get-MgDirectoryRole -All to retrieve all roles that are currently activated in the tenant.
For each member in a role:
Only includes users whose creation date is within the last 90 days.
Uses a hashtable to store each admin user only once, and aggregates their roles before printing a neatly formatted table.
Here are a few ways to take this script to the next level:
-Property JobTitle, Department
$recentAdmins.Values | Export-Csv -Path "RecentAdmins.csv" -NoTypeInformation
Store CreatedDateTime and sort using:
Sort-Object 'CreatedDateTime' -Descending
Trigger alerts via Send-MailMessage if newly created admins are detected.
| Error Message | Cause | Solution |
| Global Administrator role not found | Role not activated in tenant | Assign at least one user to activate the role |
| Access Denied | Insufficient permissions | Use appropriate Graph scopes (e.g., Directory.Read.All) |
| @odata.type not accessible | Returned object is not a user | Check object type with .AdditionalProperties.'@odata.type' |
| CreatedDateTime is null | Property not returned by API | Ensure it is explicitly requested via -Property |
Here’s why this script is valuable to Microsoft 365 admins and security teams:
Tracking recently created Microsoft 365 admin accounts is a proactive security measure. It gives IT admins the ability to detect irregular admin role assignments, audit onboarding processes, and ensure that access control is tight.
By using this Graph PowerShell script, you can stay ahead of potential threats and maintain full visibility over privileged access in your environment.
© m365corner.com. All Rights Reserved. Design by HTML Codex