If you are looking for a easier and a faster way to assign M365 license, then you have landed on the right page. Instead of using the M365 admin portal, Microsoft Graph PowerShell SDK is the new shiny tool to automate the assignment of license.
What is Graph PowerShell SDK
Microsoft Graph PowerShell Module consists of a collection of PowerShell modules that contain commands for calling Microsoft Graph API. The module acts as an API wrapper for the Microsoft Graph APIs, exposing the entire API set for use in PowerShell.
Microsoft Graph PowerShell is the replacement for the Azure AD PowerShell and MSOnline modules and is recommended for interacting with Azure AD.
Prerequisites for installing Graph PowerShell SDK
- Install PowerShell 7
- Or upgrade to PowerShell 5.1 or later which will require the following:
- Install .Net 4.7.2 or later
- Update PowerShellGet to the latest version
- PowerShell execution policy must be set to remote signed
To install PowerShell 7 run the command below:
The install is simple, just one line. Run the command below
iex "& { $(irm https://aka.ms/install-powershell.ps1) } -UseMSI"
Install Graph PowerShell SDK
To install Microsoft Graph PowerShell SDK, run the command below
Install-Module Microsoft.Graph -Scope CurrentUser -AllowClobber -Force
Verify graph Install
To confirm the installation of Microsoft Graph PowerShell SDK, run the command below. Microsoft.Graph is the name of the PowerShell module.
Get-InstalledModule Microsoft.Graph
Ok, after getting the prerequires out the way, it’s time to get into the fun stuff. Since the objective is to automate the assignment of M365 licenses, we need to create a service principle (App registration) in Azure AD. The steps are listed below.
Create App Registration in Azure AD
Log into the Azure portal and navigate to Azure Active Directory > App registration > and click on New registration and enter the requested information.

- Name – enter the name of the application
- Supported account types – select Accounts in this organizational directory only (only – Single tenant)
- Redirect URI (optional) – Select Web > URL address = http://localhost > then click register

After the application is created, write down the:
Application Client ID = 9217dj74r-cqp3-42b2-a79d-392394ad7na8 and the
Directory tenant ID = 40187a2a4-c7b8-4d2e-99f1-pnc4ca1502xu (those ID’s are not real)
You will need those values later on when connecting to Graph.
Create the application Secret:
Under Manage click on Certificates & secrets > then click on New client secret

Enter a description and an expiration date. The default is 6 months > then click Add

Remember to write down the Secret Value and the Secret ID. Once you leave the page, you will no longer have access to it. The examples below are fake. The secret will be used to connect to graph. We still have a few more configuration steps before we can connect to graph.
Secret Value: bz177~FSYPwjQKuyq-ulKh~fvZvQWFmFpuj765ut5gf
Secret ID: Pw785d43b2c-7e9f-416f-bec7-q43013589hbg6j
Configure application permission
We will choose application permission to support full automation. Since we are still under the applications settings, click on API permissions > Add a permission

Click on Microsoft Graph

Click on Application permissions:
Organization.Read.All permission scope is required to read the licenses available in the tenant. Also editing user license assignment require User.ReadWrite.All and Directory.ReadWrite.All
Link to Application Permissions
Select the suggested permissions listed above and click on Add permission

The result should look like this:

The next step is to grant admin consent. Click on Grant admin consent for “your org” and confirm

The Status should change to Green

Instead of using a secret for authentication, you can also a certificate which is more secure. If you do not have access to a PKI cert, you can create a self-signed cert.
Create self-signed certificate:
#Creating self-signed certificate
$CertParam = @{
'KeyAlgorithm' = 'RSA'
'KeyLength' = 2048
'KeyExportPolicy' = 'NonExportable'
'DnsName' = 'DESKTOP-CompName'
'FriendlyName' = 'AutomateGraphApp_Test44'
'CertStoreLocation' = 'Cert:\CurrentUser\My\'
'NotAfter' = (Get-Date).AddYears(1)
}
#Creating self signed cert with parameters from above.
$Cert = New-SelfSignedCertificate @CertParam
#view cert
$Cert | Select Subject, Thumbprint, FriendlyName
#Export the .cer and upload to Azure
Export-Certificate -Cert $Cert -FilePath C:\AssignLicense\AutomateApp_test.cer
Connect to Graph using a certificate
The Appid, TenantID and certificate values are fake for example.
$AppId = 'uqorfc34-c2d3-42b2-a79d-rt453218a1433'
$TenantId = 'hh67ds342a4-c7b8-4d2e-99f1-cc881ca150bia3'
$Certificate = Get-ChildItem Cert:\CurrentUser\My\11dd66nn33904F38516DCED11379AFE5C20867gf32d
Connect-Graph -TenantId $TenantId -AppId $AppId -Certificate $Certificate
If successful the screen will say, “Welcome of Microsoft Graph!”
Connect to Graph using client secret
#Install MSAL.PS module for all users (requires admin rights)
Install-Module MSAL.PS -Scope AllUsers -Force
#Generate Access Token to use in the connection string to MSGraph
$AppId = '49gf3w24c-c2d3-42b2-a79d-392394a7hh32'
$TenantId = 'ss8k75f2a4-c7b8-4d2e-99f1-f3c4cafj6mq8hr5'
$ClientSecret = 'bb.81g~FSYyyh85KvQv-ulKh~fvZvQWFmFp11fk83g'
Import-Module MSAL.PS
$MsalToken = Get-MsalToken -TenantId $TenantId -ClientId $AppId -ClientSecret ($ClientSecret | ConvertTo-SecureString -AsPlainText -Force)
#Connect to Graph using access token
Connect-Graph -AccessToken $MsalToken.AccessToken
Select the Graph Profile
By default the Microsoft Graph PowerShell commands target the v1.0 API version. Commands for APIs that are only available in beta aren’t available in PowerShell by default. If you run into errors running the script below, just change the Graph profile to beta. The GA version of Graph is v1.0 and the preview version is Beta.
To view the current version, use the Get command. To change the current version, use the Select command below. See the commands below
#displays the current version
Get-MgProfile
#change the current version
Select-MgProfile -Name Beta #or v1.0
PowerShell Script
Customers upgrade from O365 E3 to M365 E5 licenses all the time. Below you will find an example script to remove the old license and add the new M365 E5 license. I hope this helps.
# connect to Graph Service
$AppId = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
$TenantId = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
$Certificate = Get-ChildItem Cert:\CurrentUser\My\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx #that is the thumbprint
Connect-Graph -TenantId $TenantId -AppId $AppId -Certificate $Certificate
#Set Graph Profile
Select-MgProfile -Name beta
#Get the SKU and plan info
$O365g3Sku = Get-MgSubscribedSku -All | Where SkuPartNumber -eq 'ENTERPRISEPACK_GOV'
$O365g3SkuEXDisabled = $O365g3Sku.ServicePlans | Where ServicePlanName -in ("EXCHANGE_S_ENTERPRISE_GOV") | Select -ExpandProperty ServicePlanId
$M365g3Sku = Get-MgSubscribedSku -All | Where SkuPartNumber -eq 'M365_G3_GOV'
#Export User types for documentation pre-run
Get-MgUser -Filter "assignedLicenses/any(x:x/skuId eq $($O365g3Sku.SkuId) )" -ConsistencyLevel eventual -CountVariable e5licensedUserCount -All | Select ID, DisplayName, UserPrincipalName | Export-Csv c:\temp\All_G3_Users_PreRun.csv
#get the exchange disabled users here
#Get users with G3 license (all users)
$G3Users = Get-MgUser -Filter "assignedLicenses/any(x:x/skuId eq $($O365g3Sku.SkuId) )" -ConsistencyLevel eventual -CountVariable e5licensedUserCount -All
# Unassign E3, Assign M3
Foreach ($User in $G3Users) {
Set-MgUserLicense -UserId $User.ID -AddLicenses @{} -RemoveLicenses @($O365g3Sku.SkuId)
Set-MgUserLicense -UserId $User.ID -AddLicenses @{ SkuId = M365g3Sku.SkuId } -RemoveLicenses @()
}
THE END 🙂
You must log in to post a comment.