Every time HR announces a new hire, IT administrators face a familiar checklist: create the user account, assign a temporary password, figure out which licenses they need, and manually add them to half a dozen Microsoft 365 groups. Manual onboarding is not only a massive drain on IT resources, but it also inevitably leads to human error—misspelled names, forgotten licenses, or missing permissions.
By leveraging the Microsoft Graph PowerShell SDK, you can transform this tedious chore into a seamless, automated workflow. In this guide, we will walk you through the process of automating Microsoft 365 user onboarding from start to finish using modern Graph API commands.
The Automated Onboarding Workflow
A mature IT onboarding process should require minimal manual input. The goal is to take a set of attributes (like Name, Department, and Job Title) and let PowerShell handle the rest:
Important for Hybrid Environments
If your organization uses Microsoft Entra Connect to sync users from an on-premises Active Directory, you must create the account in Active Directory first and allow synchronization to provision the cloud identity. Creating the user directly in Entra ID will result in duplicate identities or synchronization conflicts.
Prerequisites: Connect to Microsoft Graph
The legacy MSOnline and AzureAD modules are deprecated. We will use the modern Microsoft.Graph module.
To automate user creation, group assignments, and verify existence, you need specific API scopes. Microsoft distinguishes between Delegated Access (interactive) and App-only Access (unattended automation).
Interactive (Delegated Access)
If you are running the script manually from your workstation:
$TenantId = "yourtenant.onmicrosoft.com"
$Scopes = @(
"User.ReadWrite.All",
"GroupMember.ReadWrite.All",
"Group.ReadWrite.All",
"Directory.Read.All"
)
Connect-MgGraph -TenantId $TenantId -Scopes $Scopes -Interactive
Unattended Automation (App-Only / Managed Identity)
If you are running this as an Azure Automation Runbook, you should use a Managed Identity or Certificate authentication. This is the Microsoft recommended approach for enterprise automation.
# Using a System-Assigned Managed Identity in Azure Automation
Connect-MgGraph -Identity
# Or using an App Registration with a Certificate
Connect-MgGraph -TenantId $TenantId -ClientId $ClientId `
-CertificateThumbprint $Thumbprint
Step 1: Create the User Account (Safely)
The core of the onboarding script is the New-MgUser cmdlet. A robust script must handle UPN conflicts (when a user with the same name already exists) and generate passwords that comply with your Entra Password Protection policies.
Do not hardcode simple passwords like ChangeMe123!. Instead, use a secure generator. The script below uses a cross-platform approach compatible with both Windows PowerShell 5.1 and PowerShell 7 (Core).
$FirstName = "Alex"
$LastName = "Wilber"
$UPN = "$($FirstName.ToLower()).$($LastName.ToLower())@yourdomain.com"
$MailNick = "$($FirstName.ToLower()).$($LastName.ToLower())"
$Department = "Marketing"
$UsageLocation = "US"
# 1. Check for UPN Conflicts to prevent errors
try {
$ExistingUser = Get-MgUser -UserId $UPN -ErrorAction Stop
Write-Host "Error: User $UPN already exists!" -ForegroundColor Red
return
} catch {
Write-Host "UPN $UPN is available. Proceeding..." -ForegroundColor Green
}
# 2. Generate a secure temporary password (PowerShell 7 Compatible)
$Chars = 'abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789!@#$%^&*'
$TempPassword = -join ((1..16) | ForEach-Object {
$Chars[(Get-Random -Maximum $Chars.Length)]
})
$PasswordProfile = @{
Password = $TempPassword
ForceChangePasswordNextSignIn = $true
}
# 3. Create the user in Entra ID
$NewUser = New-MgUser -DisplayName "$FirstName $LastName" `
-GivenName $FirstName -Surname $LastName `
-UserPrincipalName $UPN -MailNickname $MailNick `
-Department $Department -UsageLocation $UsageLocation `
-AccountEnabled:$true -PasswordProfile $PasswordProfile
# 4. Verify Creation
if ($NewUser.Id) {
Write-Host "User $($NewUser.UserPrincipalName) created successfully." -ForegroundColor Green
}
Step 2: Assign Licenses (The Smart Way)
While you could use Set-MgUserLicense to directly assign an E3 or E5 license, this is an anti-pattern. Direct license assignments lead to management nightmares and “license sprawl” down the line.
Instead, if your organization already uses Entra Group-Based Licensing, no additional license assignment code is required. Because we set the user’s Department attribute to “Marketing”, an Entra Dynamic Group (e.g., All-Marketing-FTE) will automatically pull them in and assign the correct Microsoft 365 license.
Asynchronous Provisioning Note
Group membership evaluation and license assignment are asynchronous processes. It may take several minutes (or sometimes longer) before Exchange Online mailboxes, Teams, and SharePoint resources are fully provisioned and ready for the user.
Step 3: Add User to Security Groups and Teams
To add the user to specific project groups or Microsoft Teams that aren’t dynamically populated, use the New-MgGroupMember cmdlet.
# The Object ID of the "Marketing Projects" M365 Group or Team
$GroupId = "a1b2c3d4-5678-90ab-cdef-1234567890ab"
try {
New-MgGroupMember -GroupId $GroupId `
-DirectoryObjectId $NewUser.Id
Write-Host "Added user to Marketing group." -ForegroundColor Green
} catch {
Write-Host "Failed to add user to group: $_" -ForegroundColor Red
}
Advanced automation scenarios can also use New-MgGroupMemberByRef, which aligns directly with the Graph API member reference REST endpoint.
Common Onboarding Challenges and Solutions
Even with automation, you may encounter environmental hurdles. Here is how to handle the most common issues:
| Issue | Solution |
|---|---|
| Duplicate UPN / MailNickname | Always implement a Get-MgUser lookup before creation. If a conflict exists, auto-increment the UPN (e.g., alex.wilber2@...). |
| License not assigned | Verify that the user’s attributes perfectly match your Dynamic Group rules, and wait for the Entra ID evaluation cycle to complete. |
| Teams access delayed | Wait for the backend provisioning sync. Microsoft 365 backend sync can sometimes delay access to Teams channels by 15-30 minutes. |
| User cannot sign in | Ensure UsageLocation was set correctly. Microsoft 365 cannot assign a license without a valid usage location, which breaks sign-in. |
| Mailbox not created | Check the Exchange Online provisioning status. An invalid license or missing Exchange service plan will block mailbox creation. |
Conclusion
By transitioning your onboarding process to the Microsoft Graph PowerShell SDK, you eliminate manual errors, ensure consistent attribute tagging, and dramatically reduce the time it takes for a new hire to become productive.
As your organization grows, keeping track of these automated accounts—especially when employees eventually leave—becomes critical. To maintain a clean and secure tenant without writing complex lifecycle management scripts from scratch, consider exploring automated governance tools like SPClean. SPClean helps ensure that the accounts you dynamically provision today don’t become orphaned security risks or wasted licenses tomorrow.



