๐ฅ Recipe ยท User & Group Management
Bulk Create M365 Users, Assign Licenses, and Export Credentials CSV
Provision a batch of Microsoft 365 users with licenses, group membership, directory roles, and a downloadable credentials CSV for handoff
Complexity
Intermediate
Impact
user-management + provisioning + licensing + automation + onboarding
Context
Why This Matters
This recipe handles end-to-end bulk onboarding for a cohort of new Microsoft 365 users โ a common workflow when onboarding a new team, pilot group, contractor batch, or beta user cohort. Creating users one-by-one in the admin center is slow and error-prone when you also need to assign licenses, add group memberships, delegate directory roles, and hand credentials back to the requester.
Run this when you need to:
- Onboard a batch of 3โ50+ users in a single operation
- Ensure consistent attributes (department, usage location, license SKU) across the cohort
- Produce a CSV of initial passwords for secure handoff to the requesting manager or the users themselves
- Assign the same directory role or group membership to all users in the batch
The workflow creates each user with a randomly-generated 16-character password, forces password change on first sign-in, assigns an available SKU (e.g. E5, Business Premium, Developer), adds each user to a target group, optionally grants a directory role, and exports a credentials.csv file that can be downloaded once.
Expected Outcomes
After running this recipe you will have:
- N new user accounts created in Microsoft Entra ID with consistent attributes (
displayName,userPrincipalName,givenName,surname,department,usageLocation) - A license assigned to each user from the specified SKU (licenses consumed from tenant availability)
- All users added as members of the target security or Microsoft 365 group
- Directory role granted (optional) โ e.g. User Administrator โ to each user
- A downloadable CSV file with columns
Name,Email/UPN,Initial Passwordfor secure handoff - Force-change-password-on-next-signin set on every account, so initial passwords are one-time use only
Risks & Considerations
โ ๏ธ Warnings & Gotchas
- CSV contains plaintext passwords. Treat the output file as a secret. Deliver via a secure channel (password manager vault, encrypted email, Teams private chat with expiration) and delete the local copy after handoff.
- Do not reuse the CSV. Once users sign in and change passwords, the values in the file are stale. Regenerate if needed.
- License availability. Check
consumedUnitsvsprepaidUnits.enabledon the target SKU before running. The script will fail partway through if the tenant runs out of seats. - UPN domain must be verified. If you use a custom domain in the UPN, it must be verified on the tenant (
isVerified: true) or user creation returns 400 Bad Request. - Usage location is required for licensing. The
usageLocationattribute (ISO 3166-1 alpha-2, e.g.US,GB,DE) must be set before callingassignLicense, or the call returns an error. - Directory role assignment is privileged. Granting User Administrator or similar roles is a privileged action โ confirm the business justification and log the change in your change-management system.
- Avoid hardcoding passwords in scripts. The script below generates them at runtime and never persists them outside the CSV artifact.
- Idempotency. Re-running the script with the same UPNs will fail with 409 Conflict. Add a pre-check or an
-IfNotExistsflag if you need re-runnable behavior.
Required Permissions
| Permission | Why It's Needed |
|---|---|
| User.ReadWrite.All | Create user accounts, set password profiles, update attributes |
| Directory.ReadWrite.All | Assign licenses and directory roles |
| Group.ReadWrite.All | Add users to the target group |
| Organization.Read.All | List subscribed SKUs to find the license skuId |
| RoleManagement.ReadWrite.Directory | Assign directory roles such as User Administrator |
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