The Office 365 admin portal provides a simple web interface for managing license assignments. It's easy to add a license for a user, or for multiple users, enable or disable sub-SKU features (the individual services that are included in a license), or remove a license. Licenses for multiple users can be managed at the same time. This method is useful for ad-hoc license management, or for bulk assigning licenses when you first provision an Office 365 tenant. The web interface is friendly for even a non-technical user, so license management tasks can be delegated to people outside of IT support if necessary.

Azure Active Directory group-based licensing, which I wrote about here, simplifies license management by mapping license assignments to groups. License management for end users is then a simple task of adding or removing users in groups, and doesn't require the ongoing use of Office 365 management tools.

In this article I'm going to demonstrate how to manage Office 365 licenses using PowerShell. This is more complex than either of the previous methods, but is useful for automating license assignments as part of a user provisioning process. PowerShell is also a good method for querying license usage and generating your own custom reports for license consumption, which can help you to manage your costs over time.

The Azure AD V2 PowerShell Module

License management in Office 365 is performed using the Azure Active Directory PowerShell module. The first version of this PowerShell module is also known as the MS Online module, and uses cmdlets with “Msol” in the name, for example Connect-MsolService and Get-MsolUser.

While the MS Online module is still available today, it will be deprecated in the near future. A new Azure Active Directory PowerShell V2 module has been developed to replace it. This module is also known as the Azure AD module. The Azure AD module uses the Office 365 Graph API to interact with Office 365. Microsoft aims to migrate the functionality of the MS Online module to the Azure AD module, and recommends that you use Azure AD for any script development. In this blog post I will demonstrate license management using the Azure AD module.

The Azure AD module is installed using PowerShellGet, which is included with Windows Management Framework (WPF) 5.0 (PowerShell 5.0). Windows 10 and Windows Server 2012 R2 or later ship with PowerShell 5.0 installed by default, which means that PowerShellGet is already available. For earlier operating systems, you'll either need to upgrade to WMF 5.0, or install PowerShellGet for PowerShell 3.0 or 4.0. Some applications such as Exchange Server are sensitive to changes in the version of WMF that is installed on the system, so you should not upgrade WMF until you've verified that all your installed software will continue to work

1

PSC:\>Install-Module AzureAD

After the Azure AD module is installed you can connect to your Office 365 tenant by running the Connect-AzureAD cmdlet, and then entering your admin credentials when prompted. The Azure AD module supports the use of multi-factor authentication (MFA).

1

PSC:\>Connect-AzureAD

To explore the available cmdlets in the Azure AD module, run the following command.

1

PSC:\>Get-Command-Module AzureAD

As a side note, Connect-AzureAD will work with stored credentials function as long as your account does not require MFA or you're connecting from a network that allows MFA to be bypassed.

In the output above we can see that my tenant has 25 “ENTERPRISEPACK” licenses, and 5 “EMS” licenses. The SkuPartNumber for each does not precisely match the name of the license that you'll see in Office 365 documentation or in the license management sections of the Office 365 admin portal. For example, ENTERPRISEPACK is the SkuPartNumber for the Enterprise E3 license, while EMS is the SkuPartNumber for the Enterprise Mobility and Security E3 license. A complete list of part numbers and friendly names isn't available on Microsoft online documentation sites, although with a little searching and common sense you can usually work out what they mean. If there's any confusion, opening a support ticket with Microsoft will get you the answers you need.

The individual license features and services, also referred to as sub-SKU features, can also be inspected. As with the SkuPartNumber values, the ServicePlanName values are not a match for the friendly names that you see in the Office 365 or Azure admin portals, but names like SWAY, POWERAPPS_O365_P2, and EXCHANGE_S_ENTERPRISE are obvious. Others are not so obvious, such as MCOSTANDARD (Skype for Business Online), but again some searching online will usually clear up any confusion.

In the output above we can see the SkuId of the license that is assigned to the user. The matching license can be found by running Get-AzureADSubscribedSku, which in the ouput below we can see is the ENTERPRISEPACK license (Enterprise E3).

The Get-AzureADUser output shown above also reveals the DisabledPlans property. This property contains the ServicePlanId values of the sub-SKU features that have been disabled for the user. There are two ways to match those ServicePlanId values to the actual names of the sub-SKU features. The first is to use the output of Get-AzureADSubscribedSku to view the ServicePlanId values for the individual services, as demonstrated earlier. For the example of Jane Tulley, the ID of the disabled plan is “7547a3fe-08ee-4ccb-b430-5077c5041653”, which is YAMMER_ENTERPRISE in the list of service plans for the ENTERPRISEPACK license.

The other approach is to look at the AssignedPlans property of the user.

In the output above we can see that the “YammerEnterprise” service is suspended, and has a ServicePlanId matching the ID in the list of DisabledPlans we saw earlier.

You will also notice that the service names returned in the Get-AzureADUser output do always not match the service plan names returned in the Get-AzureADSubscribedSku output. For example, Get-AzureADUser shows a service name of “TeamspaceAPI” whereas Get-AzureADSubscribedSku shows the same service as “TEAMS1”. These differences are mildly irritating but do reinforce the idea that you should match two difference pieces of data by the ServicePlanId, not by the friendly name, whenever you are running PowerShell cmdlets or writing scripts to manage your licenses.

For administrators who are familiar with using the MS Online PowerShell module to manage licenses, there is one minor difference to be aware of. The Get-AzureADUser and Get-MsolUser cmdlets return slightly different information for the same user object. Get-AzureADUser will only return sub-SKU features that are Enabled, Deleted or Suspended, whereas Get-MsolUser will return the status of all sub-SKU features. Here's an example, using an account where I've disabled several sub-SKU features to demonstrate the differences in cmdlet output.

Assigning a Single License Using PowerShell

The Set-AzureADUserLicense cmdlet assigns and removes Office 365 licenses to user accounts. A simple example is assigning a license to a new user account. Before assigning the license, the usage location of the account also needs to be configure. The license assignment process involves a series of steps to:

Create an assigned license (singular) object

Add the assigned license object to another object representing the assigned licenses (plural)

Run Set-AzureADUserLicense and provide the value for the assigned licenses (plural)

To perform those steps we need to know the ObjectId of the user account, and the SkuId of the license.

Assigning Multiple Licenses Using PowerShell

Using the same steps as above you can assign an additional license to a user. For example, if we wanted to add the EMS license to the user who is already licensed for Enterprise E3, we could simply re-run the steps above using the SkuId for the EMS license.

If you would like to assign multiple licenses at the same time you can do so with just a small modification to the process. Remember, we're creating an assigned license (singular) object, and adding it to an assigned licenses (plural) object. We can add multiple assigned license (singular) objects by repeating those commands. Here's an example of licensing a user for Enterprise E3 and EMS at the same time.

In the output above you might notice that Intune, which is included with the EMS license, is not listed as a service. This is another example of how Get-AzureADUser doesn't show services that are not in an enabled, suspended, or deleted state. Intune requires activation for the user, and is in a “PendingInput” state when the license is initially assigned to the user as you can see in the Get-MsolUser output below.

Assigning Licenses with Sub-SKU Features Disabled

Office 365 licenses such as Enterprise E3 and E5 allow access to multiple services and applications. For some organizations it is required to disable some of the features of a license, either because the feature should not be used in that environment, or simply to manage a staged roll out and adoption of Office 365 features.

To assign a license with sub-SKU features disabled we use the same process demonstrated earlier, but this time we need to configure the license object with enable and disabled plans before applying the license to the user. For this example I'll assign an E3 license but only enabled the Exchange Online mailbox and the Office 365 ProPlus applications.

Removing Licenses Using PowerShell

For the final demonstration in this article let's look at how to remove an assigned license using PowerShell. The Set-AzureADUserLicense cmdlet is used for this task, and the process is similar to adding a license. The difference is that when creating the assigned licenses (plural) object we use RemoveLicenses instead of AddLicenses, and provide only the SkuId instead of the full license object.

Summary

As you can see, managing Office 365 licenses with the Azure AD V2 PowerShell module is a complex task at first, but once you've performed the steps a few times it should become much more comfortable. Azure AD group-based license management is simpler, but won't fit everyone's needs. Using PowerShell to manage licenses like this will suit organizations who want to automated license assignments into other processes. The use of the Graph API also means you can ignore the Azure AD module itself and write custom code to interact with the REST API to perform the same tasks. That is out of scope of this blog post, but it's something you can explore if custom development and integration into third party systems is a requirement for you.

Comments

Hi Paul
Great article…
Trying to make reporting on a user readable for humans without memorising each SkuId. Has anyone managed a script that gives
The License SkuPartNumber assigned
The assigned License ServicePlanName
Preferably parsable as an object for reporting…
This is my output and its terrible…

This probably won’t help you, but maybe it will help someone else who reads your blog. Your bit on removing licenses was helpful; however, we have a ton of SKUs. There’s no way my Junior Admins or I will remember the SkuIDs for these…so I needed a way to easily remove licenses from a user account without having that information. I wrote this module:

1) All users were globally disabled Teams (when that was a thing, which it isn’t now), and we want to add that SubSKU (Teams) back in for all enabled / licensed Users.

2) When we piloted Teams, a group of 20 users were given the Teams SubSKU to allow them to evaluate Teams. If 1), above, works, what will happen to those 20 users. Would the script need to iterate through and skip them if they were already enabled for Teams, or would it just enable it again and continue.

Using the get-azureaduser and get-azureaduserlicensedetail I can easily see what license are assigned. Is there a way to determine if the license is directly applied, or applied using Azure AD group based licenses? I found a way using the MSOL module, but not the AzureAD module.

I have a similar question about cmdlets and methods for viewing licenses assigned using security groups. I have the methods that exist today in the MSOnline module will have counterparts in AzureAd module. This is hoping that that v2 supports more features — not less.

“AdHoc License Administrator” role has been deprecated and “User administrator” role is required at the minimum for managing the licenses.

“User administrator” role gives more access than what I would like to give to the account running the provisioning scripts. Have you found a method to delegate only “License management” permissions to the account running the provisioning scripts.

Hello Thank you very much for your article. I was wondering. If i have many users, and want to add a licence for all this users? How can i do it? Do i need a csv file or muss write my code in a for each loop? Please can you help me or give me more informations?
Thank you

Hi Paul, have you noticed, or is it just me, that the Get-AzureADSubscribedSku now no longer returns the ServicePlans objects with each Sku object but instead returns a string that looks like the following:

Just wanting to do a sanity check before I start building some code to parse those strings for the ServicePlanId and ServicePlanName. Looks like this is YAML output, essentially, except for the class declaration.

thanks for the article. i am looking for a way to Enabled individual ServicePlan for existing users. we use E3 license with only have a few service plans enabled, now we want to enable more plans, such as “Team”. How can we do that without removing the whole license and re-add.