How to Find When Azure AD User Accounts Receive Microsoft 365 Licenses

Licensing Report Has No Dates

I recently published a article explaining how to create a licensing report for an Office 365 tenant using cmdlets from the Microsoft Graph SDK for PowerShell.

A reader asked: “I am trying to determine when a specific license, in this case an E3 Security and Mobility license, was added for all users.”

No Dates for Licenses

It’s an interesting question. As written, my script generates a report based on the licenses and service plans assigned to user accounts. However, it doesn’t do anything to tell you when a license for a product like Enterprise Security and Mobility E3 (EMS E3) is assigned to a user. This is because Azure AD does not record assignment dates for the product license information held for user accounts. Instead, license information for an account is presented as a table of SKU identifiers with any disabled service plans in a SKU noted:


DisabledPlans                          SkuId
-------------                          -----
{bea4c11e-220a-4e6d-8eb8-8ea15d019f90} b05e124f-c7cc-45a0-a6aa-8cf78c946968
{}                                     8c4ce438-32a7-4ac5-91a6-e22ae08d9c8b
{}                                     4016f256-b063-4864-816e-d818aad600c9
{a23b959c-7ce8-4e57-9140-b90eb88a9e97} 6fd2c87f-b296-42f0-b197-1e91e994b900

However, date information is included in the service plan information for an account:


AssignedDateTime    CapabilityStatus Service                       ServicePlanId
----------------    ---------------- -------                       -------------
09/11/2021 10:33:37 Enabled          AzureAdvancedThreatAnalytics  14ab5db5-e6c4-4b20-b4bc-13e36fd2227f
09/11/2021 10:33:37 Enabled          AADPremiumService             eec0eb4f-6444-4f95-aba0-50c24d67f998
09/11/2021 10:33:37 Enabled          RMSOnline                     5689bec4-755d-4753-8b61-40975025187c
09/11/2021 10:33:37 Enabled          SCO                           c1ec4a95-1f05-45b3-a911-aa3fa01094f5
09/11/2021 10:33:37 Enabled          AADPremiumService             41781fb2-bc02-4b7c-bd55-b576c07bb09d
09/11/2021 10:33:37 Enabled          MultiFactorService            8a256a2b-b617-496d-b51b-e76466e88db0
09/11/2021 10:33:37 Enabled          RMSOnline                     bea4c11e-220a-4e6d-8eb8-8ea15d019f90
09/11/2021 10:33:37 Enabled          RMSOnline                     6c57d4b6-3b23-47a5-9bc9-69f17b4947b3
09/11/2021 10:33:37 Enabled          Adallom                       2e2ddb96-6af9-4b1d-a3f0-d6ecfd22edb2

Checking Dates for Service Plan Assignments

Given that date information is available for service plans, it should therefore be possible to check against the service plan information for user accounts to find assignments of a service plan belonging to a product (SKU). Looking at the Product names and service plan identifiers for licensing page , we find the list of service plans included in EMS E3 (SKU identifier efccb6f7-5641-4e0e-bd10-b4976e1bf68e). The set of service plans are:

  • Azure Active Directory Premium P1: 41781fb2-bc02-4b7c-bd55-b576c07bb09d
  • Azure Information Protection Premium P1: 6c57d4b6-3b23-47a5-9bc9-69f17b4947b3
  • Cloud App Security Discovery: 932ad362-64a8-4783-9106-97849a1a30b9
  • Exchange Foundation: 113feb6c-3fe4-4440-bddc-54d774bf0318
  • Microsoft Azure Active Directory Rights: bea4c11e-220a-4e6d-8eb8-8ea15d019f90
  • Microsoft Azure Multi-Factor Authentication: 8a256a2b-b617-496d-b51b-e76466e88db0
  • Microsoft Intune: c1ec4a95-1f05-45b3-a911-aa3fa01094f5

The theory is that you should be able to check accounts assigned EMS E3 to retrieve information about one of the service plans in the SKU and retrieve and report the assigned date. I don’t have EMS E3 in my tenant, but I do have EMS E5. I therefore checked the theory by running this PowerShell code:

# Check the date when a service plan belonging to a product like EMS E3 is assigned to an account
$EMSE3 = "efccb6f7-5641-4e0e-bd10-b4976e1bf68e" # Product SKU identifier for Enterprise Mobility and Security E3
$EMSE5 = "b05e124f-c7cc-45a0-a6aa-8cf78c946968" # Product SKU identifier for Enterprise Mobility and Security E5
$TestSP = "41781fb2-bc02-4b7c-bd55-b576c07bb09d" # Azure Active Directory Premium P1
$Report = [System.Collections.Generic.List[Object]]::new()
# Find tenant accounts
Write-Host "Finding Azure AD accounts..."
[Array]$Users = Get-MgUser -Filter "UserType eq 'Member'" -All | Sort DisplayName
ForEach ($User in $Users) {
  ForEach ($SP in $User.AssignedPlans) {
   If (($User.AssignedLicenses.SkuId -contains $EMSE5) -and ($SP.ServicePlanId -eq $TestSP -and $SP.CapabilityStatus -eq "Enabled")) {
        $ReportLine = [PSCustomObject][Ordered]@{  
          User            = $User.DisplayName
          UPN             = $User.UserPrincipalName
          ServicePlan     = $SP.Service
          ServicePlanId   = $SP.ServicePlanId 
          Assigned        = Get-Date($SP.AssignedDateTime) -format g
    } #End if
  } #End ForEach Service plans
} #End ForEach Users

After defining some variables, the code calls the Get-MgUser cmdlet to find the Azure AD accounts in the tenant (I used the script described in this article as the basis; see this article for more information about the Microsoft Graph SDK for PowerShell). Make sure that you connect to the beta endpoint as license information is not available with the V1.0 endpoint (run Select-MgProfile beta after connecting to the Graph).

Next, the code checks the assigned plans and if the desired plan belongs to the right product and is enabled, we report it. Each line in the report is like this:

User          : Kim Akers
UPN           :
ServicePlan   : AADPremiumService
ServicePlanId : 41781fb2-bc02-4b7c-bd55-b576c07bb09d
Assigned      : 11/11/2017 16:52

This is a quick and dirty answer to the problem of discovering when a product license is assigned to user accounts. It might serve to fill in while Microsoft improves matters.

As reported by Vasil Michev, Microsoft recently added a licenseAssignmentState resource to the Graph API. This isn’t yet available for PowerShell, but the date information can be retrieved using the Graph. In this snippet, we find user accounts and examine their assignment state for EMS E5 to discover when the license was assigned. The code assumes that you’ve already used a registered app to authenticate and fetch an access token to interact the Graph APIs. Remember that you might need to use pagination to fetch all the pages of user data available in the tenant. Anyway, here’s my quick and dirty code to prove the point:

# Use the Graph API to check license assignment states
Write-Host "Fetching user information from Azure AD..."
$Uri = "`$filter=userType eq 'Member'"
[Array]$Users = (Invoke-RestMethod -Uri $Uri -Headers $Headers -Method Get -ContentType "application/json")
$Users = $Users.Value

Write-Host “Processing users…”
ForEach ($User in $Users) {
    $Uri = "" + $User.UserPrincipalName + "?`$select=licenseAssignmentStates"
    [Array]$Assignments = Get-GraphData -Uri $Uri -AccessToken $Token
    ForEach ($License in $Assignments.LicenseAssignmentStates) {
        $LicenseUpdateDate = $Null
        If ($License.SkuId -eq $EMSE5 -and $License.State -eq "Active") {
           If ([string]::IsNullOrWhiteSpace(($License.lastUpdatedDateTime)) -eq $False ) {
              $LicenseUpdateDate = Get-Date($License.lastUpdatedDateTime) -format g }
           Else {
              $LicenseUpdateDate = "Not set" }
           Write-Host ("Last update for EMS for {0} on {1}" -f $User.DisplayName, $LicenseUpdateDate) }
    } # End ForEach License
} # End ForEach User

Last update for EMS for Tony Redmond on 15/07/2021 15:28
Last update for EMS for Andy Ruth (Director) on Not set
Last update for EMS for Kim Akers on 26/10/2021 16:58
Last update for EMS for Jack Hones on Not set
Last update for EMS for Oisin Johnston on 03/10/2020 13:18

The dates retrieved using this method differ to the values you get from service plans because Microsoft is populating these values using the last licensing change made to the account. However, in the future, the dates will be more accurate and usable because they will capture changes, hopefully when PowerShell access is possible.

No Audit Data

In passing, I note that the Office 365 audit log captures a “Change user license” audit record when an administrator updates the licenses for an account. However, the audit record doesn’t include details of what licenses were added, changed, or removed. The Azure AD team could do a better job of capturing audit information about license updates. I’m sure they’ll be happy to hear that.

Keep up with the changing world of the Microsoft 365 ecosystem by subscribing to the Office 365 for IT Pros eBook. Monthly updates mean that our subscribers learn about new development as they happen.

3 Replies to “How to Find When Azure AD User Accounts Receive Microsoft 365 Licenses”

  1. I was experimenting with this today, but when I do the get-mguser query, the assignedplans is always blank. Any idea what would cause this?

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.