Skip to main content
Automation Chronicles

Automating M365 Administration with Microsoft Graph API

James Wilson
February 20, 2024
9 min read

For years, the AzureAD and MSOnline PowerShell modules were the bread and butter of Microsoft 365 administrators. But as Microsoft deprecates these older modules, the future is clear: Microsoft Graph API.

Graph API provides a unified programmable model that you can use to access a tremendous amount of data in Microsoft 365, Windows 10, and Enterprise Mobility + Security.

At 143IT, we've migrated hundreds of legacy scripts to the Microsoft Graph SDK. Here is how you can get started.

Why Switch to Graph?

  1. Performance: Graph is significantly faster, especially for large queries.
  2. Security: Supports modern authentication and granular scopes (Least Privilege).
  3. Coverage: It covers everything—Teams, SharePoint, Exchange, Intune, and Entra ID (formerly Azure AD).

Getting Started: The Microsoft Graph PowerShell SDK

You don't need to be a developer writing raw HTTP requests to use Graph. Microsoft provides a PowerShell SDK that wraps the API.

# Install the module
Install-Module Microsoft.Graph -Scope CurrentUser

# Connect with specific scopes (Least Privilege!)
Connect-MgGraph -Scopes "User.Read.All", "Group.ReadWrite.All"

Example 1: Bulk User Creation

Creating users one by one in the portal is slow. Here's how to do it with Graph PowerShell:

$users = Import-Csv "new_hires.csv"

foreach ($user in $users) {
    $passwordProfile = @{
        Password = "TempPassword123!"
        ForceChangePasswordNextSignIn = $true
    }

    New-MgUser -DisplayName $user.DisplayName `
               -UserPrincipalName $user.UPN `
               -MailNickname $user.MailNickname `
               -PasswordProfile $passwordProfile `
               -AccountEnabled $true `
               -UsageLocation "US"
               
    Write-Host "Created user: $($user.UPN)"
}

Example 2: Finding Inactive Users

Security hygiene requires identifying stale accounts. This script finds users who haven't signed in for 90 days.

# We need the SignInActivity property which is not returned by default
Select-MgProfile -Name "beta"

$date = (Get-Date).AddDays(-90)

Get-MgUser -All -Property DisplayName, SignInActivity | 
    Where-Object { $_.SignInActivity.LastSignInDateTime -lt $date } |
    Select-Object DisplayName, UserPrincipalName, @{N='LastSignIn';E={$_.SignInActivity.LastSignInDateTime}}

Example 3: Automating Teams Management

Need to create a Team for every new project?

$team = New-MgTeam -DisplayName "Project Phoenix" `
                   -Description "Migration project team" `
                   -Template @{
                       "[email protected]" = "https://graph.microsoft.com/v1.0/teamsTemplates('standard')"
                   }
                   
# Add a channel
New-MgTeamChannel -TeamId $team.Id `
                  -DisplayName "Announcements" `
                  -Description "Project announcements"

Handling Throttling

One challenge with Graph API is throttling. If you make too many requests too quickly, Microsoft will slow you down (HTTP 429).

The Graph SDK handles basic retries automatically, but for robust scripts, you should implement Invoke-MgGraphRequest with custom retry logic for complex operations.

Conclusion

The transition to Microsoft Graph might seem daunting, but it unlocks a level of automation capability that legacy modules never could. It allows you to treat your M365 tenant as a programmable platform.

Need help migrating your legacy scripts or building complex M365 automations? 143IT has the expertise to modernize your administration workflows.

About James Wilson

Senior Systems Engineer at 143IT. Expert in Microsoft ecosystem automation and identity management.

Ready to Transform Your IT?

Let's discuss how we can help you automate, evolve, and dominate.

Schedule a Consultation