๐ฅ Recipe ยท User & Group Management
Bulk Onboard Users from an Excel File Using a PowerShell and Microsoft Graph Script
Create Entra ID accounts, set profile properties, and assign group memberships in a single scripted pass driven by a simple Excel roster
Complexity
Intermediate
Impact
user-management + automation + entra-id + bulk-operations + onboarding
Context
Why This Matters
New-hire onboarding is one of the most repetitive โ and error-prone โ tasks in a Microsoft 365 tenant. Creating each user by hand in the admin center means manually entering names, setting temporary passwords, typing department and phone data, and then clicking through each group to add the new hire. When HR hands you a batch of five, ten, or fifty starters for the same day, the manual approach is slow, inconsistent, and easy to mess up.
This recipe provides a reusable PowerShell script that reads a plain Excel file (columns: Name, Phone, Groups, Department) and onboards every row into Entra ID via the Microsoft Graph PowerShell SDK. The spreadsheet becomes your source of truth: HR fills it in, you run the script, and the tenant is updated in minutes.
Run this recipe any time you need to bulk-provision accounts โ new-hire waves, intern cohorts, seasonal staff, M&A onboarding, or migrating users from another identity system where you can export a CSV/XLSX of names, phones, departments, and group memberships.
Expected Outcomes
After completing this recipe you will have:
- A parameterized PowerShell script (
Onboard-Users.ps1) that bulk-creates Entra ID users from an Excel roster. - Each new user provisioned with display name, first/last name, UPN, mail nickname, department, business phone, usage location, and a forced-change temporary password.
- Each new user added to all groups listed in the
Groupscolumn (semicolon-separated), with group IDs cached for efficiency. - Idempotent behavior โ re-running the script skips existing users and existing group memberships rather than failing.
- A
-WhatIfdry-run mode so you can preview every create and every group-add before committing. - A console summary table showing per-user status (
CREATED,EXISTED,FAILED) and per-group outcomes.
Risks & Considerations
Warnings and gotchas
- Temporary password handling. The script takes the temp password as a mandatory parameter โ do not hard-code it into the script or check it into source control. Prefer a one-time password generator or
Read-Host -AsSecureStringin production. - UPN collisions. The script builds UPNs as
firstname.lastname@domain. Two users with the same name will collide โ add a middle initial or employee ID column for large rosters. - No license assignment. This recipe creates accounts and sets
usageLocation, but does not assign licenses. Use group-based licensing on the groups you add users to, or extend the script withSet-MgUserLicense. - Group name ambiguity. Groups are resolved by
displayName. If two groups share the same name, the first match wins โ use object IDs ormailNicknamefor disambiguation in larger tenants. - Always dry-run first. Run with
-WhatIfagainst the full spreadsheet before the real run. Eyeball the UPNs and group names in the output. - Compliance. Entra ID creation events are audited. Make sure your change-management process (ticket ID, HR approval) is attached to the run, and do not commit the Excel roster with PII to a public repo.
- Rate limits. For rosters over ~100 users, expect Graph throttling. Add
Start-Sleepbetween iterations or batch with-BatchIdif needed.
Required Permissions
| Permission | Why It's Needed |
|---|---|
| User.ReadWrite.All | Create new user accounts and set department, phone, and password profile. |
| Group.ReadWrite.All | Resolve groups by display name and add new users as members. |
| Directory.Read.All | Look up existing users to detect duplicates before creating. |
The fastest way to get this done โ just ask Dex. Copy the prompt below and paste it into your Dex conversation.
For IT Admins
Paste into Dex CoAdmin