Microsoft 365 User Management
Overview
Users in Microsoft 365 (Entra ID) are the central identity object for your tenant. Every licensed service — Exchange, Teams, OneDrive, SharePoint — flows through the user object. For MSPs, user management spans onboarding new staff, offboarding leavers, license optimization, and security posture checks across customer tenants.
Anti-triggers
- Counting, listing, or auditing users without changing them — a
read-only question is cheaper and safer through the vetted query
catalogue; use the
microsoft-graphplugin'smicrosoft-graph-queryingskill. - Offboarding as one packaged action, or any user work across more
than one tenant — the multi-step sequence below is a CIPP primitive
with its own audit record; use the
cippplugin (cipp-users). - "User" meaning a PSA contact or an MSP technician — an Entra user
is neither. The customer's billing/ticket contact lives in the PSA
(
connectwise,halopsa,kaseya/autotask); the technician being scored on a CSAT survey is acrewhuuser.
User Object Key Properties
| Property | Description | MSP Relevance |
|---|---|---|
id |
Entra object GUID | Use in API calls |
userPrincipalName |
Login email (UPN) | Primary identifier |
displayName |
Full name | Display in tickets |
accountEnabled |
Active/disabled | Offboarding, lockout |
assignedLicenses |
License SKU GUIDs | License audits |
strongAuthenticationMethods |
MFA methods | Security posture |
signInActivity.lastSignInDateTime |
Last login | Inactive user detection |
jobTitle / department |
Org structure | Access grouping |
manager |
Reporting manager | Approval workflows |
usageLocation |
2-letter country | Required before license assignment |
Account Status Values
| State | accountEnabled |
Meaning |
|---|---|---|
| Active | true |
Normal working account |
| Disabled | false |
Blocked sign-in; retains data |
| Deleted (soft) | N/A | 30-day recoverable window |
| Deleted (hard) | N/A | Permanent — data gone |
License Assignment Model
M365 licenses are assigned as SKU objects. Users need a usageLocation set before any license can be assigned.
Common MSP License SKUs
| SKU Part Number | Friendly Name |
|---|---|
O365_BUSINESS_PREMIUM |
Microsoft 365 Business Premium |
SPE_E3 |
Microsoft 365 E3 |
SPE_E5 |
Microsoft 365 E5 |
ENTERPRISEPACK |
Office 365 E3 |
EMS |
Enterprise Mobility + Security E3 |
AAD_PREMIUM |
Entra ID P1 |
AAD_PREMIUM_P2 |
Entra ID P2 |
Graph API Patterns
List All Users
GET /v1.0/users?$select=id,displayName,userPrincipalName,accountEnabled,assignedLicenses,signInActivity&$top=100
Note:
signInActivityrequires Entra ID P1 or P2.
Get a Specific User
GET /v1.0/users/{id or userPrincipalName}?$select=id,displayName,userPrincipalName,accountEnabled,jobTitle,department,assignedLicenses,usageLocation
Search Users by Name
GET /v1.0/users?$filter=startswith(displayName,'John')&$select=id,displayName,userPrincipalName,accountEnabled
Disable a User Account
PATCH /v1.0/users/{id}
Content-Type: application/json
{
"accountEnabled": false
}
Create a New User
POST /v1.0/users
Content-Type: application/json
{
"accountEnabled": true,
"displayName": "Jane Smith",
"mailNickname": "jsmith",
"userPrincipalName": "jsmith@contoso.com",
"usageLocation": "US",
"passwordProfile": {
"forceChangePasswordNextSignIn": true,
"password": "TempP@ss123!"
}
}
Assign a License
POST /v1.0/users/{id}/assignLicense
Content-Type: application/json
{
"addLicenses": [
{ "skuId": "<sku-guid>", "disabledPlans": [] }
],
"removeLicenses": []
}
Get User's Group Memberships
GET /v1.0/users/{id}/memberOf?$select=id,displayName,groupTypes
Revoke All Sign-In Sessions
POST /v1.0/users/{id}/revokeSignInSessions
MFA Status Checking
The Softeria MCP server wraps Graph API calls. To check MFA status:
GET /v1.0/users/{id}/authentication/methods
Response includes registered methods:
#microsoft.graph.microsoftAuthenticatorAuthenticationMethod— Authenticator app#microsoft.graph.phoneAuthenticationMethod— SMS/phone#microsoft.graph.fido2AuthenticationMethod— Hardware key#microsoft.graph.windowsHelloForBusinessAuthenticationMethod— WHfB#microsoft.graph.passwordAuthenticationMethod— Password only (no MFA!)
Users with only passwordAuthenticationMethod have NO MFA enrolled.
Common MSP Workflows
New User Onboarding
- Create user with temp password (
forceChangePasswordNextSignIn: true) - Set
usageLocation - Assign license SKU
- Add to required security groups
- Create mailbox (auto-provisioned on Exchange license)
- Communicate credentials to manager
User Offboarding
- Revoke all sign-in sessions immediately
- Disable account (
accountEnabled: false) - Reset password (removes existing sessions)
- Remove licenses (preserves data, frees seat)
- Convert mailbox to shared or set auto-forward
- Remove from Teams/groups
- Transfer OneDrive ownership to manager
- Schedule hard delete after data retention period
Inactive User Detection
Users with no sign-in for 90+ days are candidates for license reclamation:
GET /v1.0/users?$filter=accountEnabled eq true&$select=id,displayName,userPrincipalName,signInActivity&$top=999
Filter results where signInActivity.lastSignInDateTime is older than 90 days, or null (never logged in).
Error Handling
| Error | Cause | Resolution |
|---|---|---|
Request_ResourceNotFound |
User GUID/UPN doesn't exist | Verify UPN spelling |
Authorization_RequestDenied |
Missing Graph permission | Check app registration scopes |
LicenseAssignmentError |
No usageLocation set |
Set location first |
Directory_QuotaExceeded |
Tenant user limit reached | Contact Microsoft |
InvalidPasswordComplexity |
Password too weak | Use 12+ char with symbols |
Permissions Required
| Task | Microsoft Graph Permission |
|---|---|
| Read users | User.Read.All |
| Create/update users | User.ReadWrite.All |
| Assign licenses | Directory.ReadWrite.All |
| Check auth methods | UserAuthenticationMethod.Read.All |
| Revoke sessions | Directory.ReadWrite.All |
Related Skills
- M365 Mailboxes - Exchange mailbox management
- M365 Licensing - License inventory and optimization
- M365 Security - MFA, sign-in risk, conditional access
- M365 API Patterns - Auth, pagination, throttling