Fetch Recently Created Microsoft 365 Admins Using Graph PowerShell

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.


The Script: List Recently Created Admin Users (Last 90 Days)

# 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
}
                            

How the Script Works

Here’s what this script does step by step:

  1. Connects to Microsoft Graph
  2. It authenticates using delegated permissions:

    • RoleManagement.Read.Directory
    • Directory.Read.All
    • User.Read.All
  3. Defines a Cutoff Date (Last 90 Days)
  4. Using (Get-Date).AddDays(-90), it calculates a date threshold to compare user creation dates.

  5. Fetches All Active Admin Roles
  6. Uses Get-MgDirectoryRole -All to retrieve all roles that are currently activated in the tenant.

  7. Scans Through Each Role's Members
  8. For each member in a role:

    • It verifies the member is a user object.
    • Retrieves key user properties including CreatedDateTime and AccountEnabled.
  9. Filters for Recently Created Admins
  10. Only includes users whose creation date is within the last 90 days.

  11. Outputs a Consolidated Table
  12. Uses a hashtable to store each admin user only once, and aggregates their roles before printing a neatly formatted table.


Further Enhancements

Here are a few ways to take this script to the next level:

  • Include Job Title or Department
  • -Property JobTitle, Department
  • Export to CSV for audit trail
  • $recentAdmins.Values | Export-Csv -Path "RecentAdmins.csv" -NoTypeInformation
  • Sort by Creation Date
  • Store CreatedDateTime and sort using:

    Sort-Object 'CreatedDateTime' -Descending
  • Email Notifications
  • Trigger alerts via Send-MailMessage if newly created admins are detected.


Possible Errors & Solutions

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

Use Cases

Here’s why this script is valuable to Microsoft 365 admins and security teams:

  • Audit Trail: Know which admin accounts were created recently, and by whom.
  • Security Reviews: Spot unauthorized or suspicious admin additions.
  • Onboarding Validation: Ensure new admins are enabled and active.
  • Reporting: Feed data into compliance dashboards for regular governance.
  • Threat Detection: Combine this with anomaly detection tools to prevent insider threats.

Conclusion

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.


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