If Microsoft 365 apps or a user show as “unlicensed”, the cause is almost always one of four categories: a license assignment never landed, identity/sync issues blocked entitlement, tenant billing or seat availability changed, or an SKU/service-plan conflict or limit prevented provisioning. This playbook gets you from observation to a targeted repair path and gives copy-paste PowerShell/Graph commands plus the checks to run before you change anything.
Quick triage: is this a user, app, or account-type problem?
Start by proving exactly which object the UI flags as unlicensed and capture authoritative state from the portals and APIs before you change anything.
- Required permissions: Global Administrator or Billing Administrator for portal checks. For PowerShell/Graph, use an account with Global Administrator, User Administrator, or Privileged Role Administrator roles, or an application with Directory.Read.All and User.Read.All for read-only queries.
- Check in the Microsoft 365 admin center.
Open the affected user. Note the Licenses and Apps section: the SKU name, whether the portal shows "Assigned", and whether any service plans are shown as disabled.
- Capture authoritative API state with Microsoft Graph PowerShell.
Connect-MgGraph -Scopes "User.Read.All","Directory.Read.All"
Get-MgUser -UserId "user@contoso.com" -Property "AssignedLicenses,AssignedPlans" | Select-Object Id,UserPrincipalName,AssignedLicenses,AssignedPlans- Fallback (if Graph access is not available): MSOnline/AzureAD modules.
Connect-MsolService
Get-MsolUser -UserPrincipalName "user@contoso.com" | Select-Object UserPrincipalName,IsLicensed,LicensesConnect-AzureAD
Get-AzureADUser -ObjectId "user@contoso.com" | Select DisplayName,UserPrincipalName,ImmutableId,DirSyncEnabledWhat to save: the AssignedLicenses array (SKU IDs), AssignedPlans provisioning states, IsLicensed boolean, and DirSyncEnabled/ImmutableId. Save these outputs and timestamps — support will ask for them.
Symptom: what you see and when it appears
You might observe one of these common symptoms:
- Portal shows the SKU as "Assigned" but apps (Outlook, Teams, Office desktop) report "unlicensed" or features are blocked.
IsLicensedis false or certainAssignedPlansentries show provisioningState errors.
- A synced user gets no license despite expected group membership.
- New hires fail to receive licenses after an automation or provisioning run.
These symptoms usually appear immediately after assignment, after an Azure AD Connect sync, or after a subscription change (seat count, SKU change).
Decision tree: narrow the cause
Answer these checks in order. Each yes/no steers you to a focused repair path.
- Does the user have an assigned SKU in
AssignedLicensesbutIsLicensedis false or someAssignedPlansare not provisioned?
- If yes → go to "SKU / service-plan limits and conflicts".
- Is
DirSyncEnabledtrue orImmutableIdset and the account synced from on-premises, and do on-prem attributes (UPN, proxyAddresses) differ from Azure AD?
- If yes → go to "Sync / identity problems".
- Does the tenant show 0 available seats for that SKU or does the subscription appear suspended or recently changed in Billing?
- If yes → go to "Tenant / billing problems".
- Is the account a guest, shared mailbox, or service principal?
- If yes → go to "Verify and special cases".
- Otherwise: the license is not assigned; go to "Assignment (individual or group-based)".
Before you start (applicability and safe checks)
Stop and collect evidence before making changes. For any change, preserve a way to revert.
- Export current license bindings for affected users.
Get-MgUser -UserId "user@contoso.com" -Property AssignedLicenses | Select-Object UserPrincipalName,AssignedLicenses- Check audit logs for recent licensing changes before editing memberships or license assignments.
- If the user is synced from on-premises, coordinate with AD/AD Connect owners. Changing
ImmutableIdor severing the sync link can orphan the account.
- If you will change licenses at scale, test on a single non-critical user first.
Fix: Assignment (individual or group-based)
Safe diagnosis before changing anything: confirm the user currently lacks the SKU and that seats are available.
- Export current assignment (diagnosis).
Get-MgUser -UserId "user@contoso.com" -Property AssignedLicenses,AssignedPlans | Select-Object UserPrincipalName,AssignedLicenses,AssignedPlans- Assign a license to the user (single-user fix).
$sku = Get-MgSubscribedSku | Where-Object { $_.SkuPartNumber -eq "ENTERPRISEPACK" }
$add = @{SkuId = $sku.SkuId}
Update-MgUser -UserId "user@contoso.com" -BodyParameter @{assignedLicenses = @($add)}Expected result: AssignedLicenses includes the SKU and AssignedPlans provisioningState moves to success.
If you use group-based licensing and the user should inherit the license:
- Force a re-evaluation by removing and re-adding group membership.
Remove-MgGroupMember -GroupId "<group-id>" -DirectoryObjectId "<user-id>"
Add-MgGroupMember -GroupId "<group-id>" -BodyParameter @{@odata.id = "https://graph.microsoft.com/v1.0/directoryObjects/<user-id>"}If the user receives the license after these steps, the issue was group membership propagation. If not, proceed to the relevant next section.
Fix: Sync / identity problems
Symptoms: user is synced, assignment exists in Azure AD but provisioning fails, or the wrong on-prem object is linked.
- Confirm Azure AD Connect health and the
ImmutableIdmapping.
Connect-AzureAD
Get-AzureADUser -ObjectId "user@contoso.com" | Select UserPrincipalName,ImmutableId,DirSyncEnabled- If
ImmutableIdis missing or incorrect, plan a controlled correction with change control. If you must setImmutableIdfor a single user, get approvals and backup.
- Set
ImmutableIdonly with full coordination.
Connect-MsolService
Set-MsolUser -UserPrincipalName "user@contoso.com" -ImmutableId "<base64-objectGUID>"Expected result: after a sync cycle, the Azure AD account aligns with the on-premises object and licensing policies apply as expected.
If you still see provisioning failures, collect Azure AD Connect health logs and sync error details before escalating.
Fix: Tenant / billing problems
Symptoms: seat counts exhausted, subscription suspended, or recent billing change.
- Check Billing > Your products in the Microsoft 365 admin center to confirm available seats and subscription status.
- If seats are exhausted, purchase seats or move the user to a different SKU that has availability. After purchase, assign licenses as in the Assignment section.
- If the subscription is suspended or in a grace period, coordinate with your billing owner or contact Microsoft Support. Collect billing activity timestamps and the tenant ID before you escalate.
Expected result: subscription state returns to active and licenses can be assigned; AssignedLicenses and AssignedPlans show normal states.
Fix: SKU / service-plan limits and conflicts
Symptoms: AssignedLicenses contains the SKU but AssignedPlans shows disabled plans or provisioning errors for specific services.
- Inspect
AssignedPlansfor provisioning states and error indicators.
Get-MgUser -UserId "user@contoso.com" -Property AssignedPlans | Select-Object -ExpandProperty AssignedPlans- If a specific service plan is disabled because of a conflict (for example overlapping licenses that disable the same plan), remove the offending SKU and reassign only the intended SKU.
# Example: replace existing SKU with a new SKU
$add = @{SkuId = "<sku-to-add-guid>"}
Update-MgUser -UserId "user@contoso.com" -BodyParameter @{assignedLicenses = @($add)}- For SKU retirement or tenant-wide SKU changes, check the Microsoft 365 admin center Notices and your subscription change log before mass edits.
Expected result: AssignedPlans provisioningState entries become success for required services.
Verify and special cases: groups, dynamic assignment, guests, shared mailboxes, service principals
Confirm the fix worked and handle special account types correctly.
- Verification check (authoritative):
Get-MgUser -UserId "user@contoso.com" -Property AssignedLicenses,AssignedPlans | Select-Object UserPrincipalName,AssignedLicenses,AssignedPlansExpected: AssignedLicenses lists the SKU and AssignedPlans provisioningState shows success for required plans.
Group-based and dynamic-group licensing failures:
- Common causes: membership not updated, external system write-protecting the group, or licensing service not yet re-evaluated.
- Single-user fix: remove and re-add membership (see Assignment section). For dynamic groups, you can force re-evaluation by temporarily editing a non-critical attribute or temporarily modifying the rule then reverting.
Guests, shared mailboxes, service principals:
- Guests: External B2B guest users have restricted entitlement. You cannot reliably grant the same licensed services to guests as to full members; check product-specific guidance and licensing entitlements before assigning.
- Shared mailboxes: Typically do not need a paid license. Assign a license only if the mailbox exceeds the free limits (for example, very large mailboxes or compliance holds). Use the Exchange admin center guidance.
- Service principals: These are application identities and are not licensed like users. If an application needs access to licensed APIs, ensure the calling user or a service account holds the required license.
If your object is one of these types, follow product-specific guidance rather than standard user-license assignment.
Collect logs, audit changes and what to include when escalating to Microsoft Support
Collect these items before you open a ticket. Bundle them with timestamps and who ran each command.
- Tenant ID (GUID), affected user's UserPrincipalName and ObjectId.
- Outputs of
Get-MgUserfor the user (AssignedLicenses,AssignedPlans),Get-MgSubscribedSku, and Azure AD Connect health status if relevant.
- Audit logs for licensing changes and group membership changes.
Commands to collect audit and sign-in logs:
Get-MgAuditLogDirectoryAudit -Filter "targetResources/any(tr:tr/userPrincipalName eq 'user@contoso.com')" | Select-Object ActivityDisplayName,ActivityDateTime,InitiatedBy
Get-MgAuditLogSignIn -Filter "userPrincipalName eq 'user@contoso.com'" | Select-Object UserDisplayName,AppDisplayName,StatusEscalation phrasing (short): start with one-sentence problem, then attach the evidence. Example opening line you can adapt:
"Tenant <tenant-id>: user user@contoso.com shows AssignedLicenses contains <SKU> but AssignedPlans provisioningState shows <error>. Attached: Get-MgUser output, Get-MgSubscribedSku output, and Azure AD Connect health report."
Preventive governance: automation, quotas, naming, monitoring and minimal checks
Practical controls that stop common recurrences.
- Seat reserve: keep a small reserve of seats for critical roles so temporary shortages don't block assignments.
- Naming and tagging: tag service accounts and licensing groups with SKU intent and owner contact so accidental changes are traceable.
- Group governance: lock critical licensing groups to admin-only membership changes and record changes in change control.
- Automation and monitoring: schedule daily reports of
Get-MgSubscribedSkuvs assigned counts, and alert when usage reaches a threshold. Schedule checks for dynamic group evaluation failures and Azure AD Connect sync errors.
- Test plans: when changing SKUs or automations, run the change on a pilot group before mass deployment.
- Runbooks: keep a short runbook that includes the exact commands to capture current state, a tested single-user fix, and the escalation bundle to collect before contacting support.
Note: product UI labels, PowerShell module names, and API permission requirements can change. Check the current Microsoft documentation for any command syntax or permission changes before you run scripts in your tenant.
Conclusion
If the quick triage points to assignment, sync, billing, or SKU conflicts you can usually fix one user in minutes and scale the fix safely once you’ve validated the single-user workflow. When in doubt, collect the evidence described above and open a support case rather than making risky global changes.
Frequently Asked Questions
Why does the portal show a user as 'Assigned' but apps still say 'unlicensed'?
Because 'Assigned' only means the SKU is bound to the user object; individual service plans can still fail during provisioning. Check `AssignedPlans` provisioningState with `Get-MgUser` to see which service plans failed and collect any provisioning error details before you change assignments.