If your organization creates a Microsoft 365 account by hand for every new person, in the Admin Center, one at a time, you already know the tax: it is slow, it does not scale, and the details get re-keyed back into another system afterward. The good news is that the entire job can live inside Salesforce, triggered by a button on the record you already work from, using the Microsoft Graph API.
This is a practical walkthrough of how that integration works, and the parts that are easy to get wrong.
Why provision from Salesforce at all
If Salesforce is already your system of record for people, students, members, or employees, then it already holds the name, the role, and the moment the account should be created (an enrollment, a hire, a status change). Provisioning from there means one team works in one place, the new account details land back on the record automatically, and there is a single audit trail for who was provisioned and when.
What you need before you start
- A Microsoft Entra app registration with application permissions for the Graph endpoints you will call, typically
User.ReadWrite.Allto create users andDirectory.ReadWrite.Allor the relevant license-management scope to assign licenses. Grant admin consent. - A Named Credential and External Credential in Salesforce to hold the OAuth client credentials flow, so your Apex never stores a token or secret in code. Salesforce refreshes the token for you.
- An available license in the tenant (for example Office 365 A1 for education) that you will assign on creation.
- A username convention decided up front, because you will generate it in code.
The provisioning flow, step by step
Once the plumbing is in place, a single action on the record runs the whole sequence:
- Build the username from your house convention (for example
firstname.lastname) off the record's fields. - Check for duplicates so two people with the same name do not collide, appending a disambiguator when they do.
- Create the user with a
POSTto the Graph/usersendpoint, setting display name, user principal name, and mail nickname. - Assign the license with a call to the user's
assignLicenseaction, so the account is usable immediately rather than sitting unlicensed. - Set a unique password generated per person, instead of a shared default, and flag it for reset on first sign-in.
- Write the new address back onto the Salesforce record so the rest of your automation can use it.
- Send a branded welcome email with the sign-in details, ideally from a template an admin can edit without a developer.
- Log the attempt, success or failure, on the record's timeline so there is a full audit trail.
All of that is one click for the person doing it, and a few well-scoped Apex callouts underneath.
Handling the messy parts
The demo always works. Production is where the edge cases live.
- Duplicate names. Decide your tie-breaker before you ship (a middle initial, a number, a program code) and apply it consistently in code, not by hand.
- Unique passwords, not a shared one. A single shared password across new accounts is a real security problem. Generate a unique one per account and require a reset at first login.
- Error handling and audit. A Graph call can fail for reasons that have nothing to do with your code (a taken username, a licensing cap, a transient outage). Catch it, surface a readable message, and log every attempt so nothing fails silently.
- Deprovisioning and license reclaim. Creation is only half the lifecycle. Inactive accounts quietly hold paid licenses. It is worth planning a deprovisioning path and a way to reclaim those licenses, the savings often dwarf the cost of the build.
Keep it secure and native
The strongest version of this integration keeps the trust posture simple: the callout goes to Microsoft Graph and nothing else, access is scoped by permission set so only the right roles can run it, credentials live in a Named Credential rather than in code, and every action is logged. Nothing about your CRM data leaves Salesforce except the specific Graph request needed to create the account.
Frequently asked questions
Can Salesforce create Microsoft 365 accounts automatically?
Yes. Using the Microsoft Graph API from Apex, Salesforce can create the user, assign a license, set a password, and write the new address back to the record, either on a button click or automatically when a record reaches a certain status.
What Graph permissions are needed to create users and assign licenses?
Typically User.ReadWrite.All to create and manage users, plus a directory or license-management scope to assign licenses, granted as application permissions with admin consent on an Entra app registration.
How do I store the Microsoft credentials securely in Salesforce?
Use a Named Credential with an External Credential configured for the OAuth client-credentials flow. Salesforce manages and refreshes the token, so no secret or access token is ever stored in your Apex.
How should duplicate names be handled?
Decide a disambiguation rule up front (a middle initial, a numeric suffix, or a program code) and apply it in code, checking the directory before you create the account so two people never collide on the same username.
From manual to one click
We built exactly this for a university that was creating student Microsoft 365 accounts by hand, and moved the whole process to a single button on the student record, delivered in three working days. You can read the full story in our Microsoft 365 provisioning case study.
If you are still creating accounts in the Admin Center one at a time, we can automate it natively in your org. Book a free consultation.