Obtaining Entra license utilization insights data via the Graph API

Yesterday, Microsoft announced the public preview of Microsoft Entra License Utilization Insights, or in other words, a set of reports that aim to give you an overview of how features that require “Premium” Entra ID licenses are being leveraged within your organization. For the time being, these Insights only cover a handful of such features, namely Conditional Access policies (for the corresponding Entra Premium P1 license requirement) and the risk-based Conditional Access policies (for Entra Premium P2). Not much, but it’s a start.

The feature itself is simple enough to use – all you need to do is access the Entra portal (or the Azure AD blade), navigate to the Usage & Insights page and select the newly introduced License utilization entry on the bottom. Instead of parroting the announcement and the official documentation on this, lets instead take a look at how the underlying data can be fetched via the Graph API. While the corresponding documentation is still not available, we can peek at the requests the UI executes.

A quick network capture reveals that the new insights use the /beta/reports/azureADPremiumLicenseInsight endpoint. As with most things Graph, the first important question we need to address is the permissions needed to query said endpoint. After some trial and error, it looks like the Reports.Read.All permission is sufficient, for either delegate and application permissions context. For the former, the user under whose identity you are running the request must also be assigned an appropriate directory role. While I didn’t bother to find the exact “minimum viable” role here, the usual suspects should do – Global reader, Reports reader, etc.

With that knowledge at hand, we can head over to the Graph explorer tool and check out the new endpoints. Here are the results from my personal tenant, where I have a whooping total of five (5) Azure AD Premium P2 licenses:

GET https://graph.microsoft.com/beta/reports/azureADPremiumLicenseInsight


As you can see from the above screenshot, the output of the report is quite simple. First, we get a handful of fields that give us the number of eligible licenses in the tenant: entitledP1LicenseCount for Azure AD Premium P1, entitledP2LicenseCount for Azure AD Premium P2 and the cumulative count given by entitledTotalLicenseCount. The actual insights are packaged within two properties, p1FeatureUtilizations for any feature requiring Premium P1, and p2FeatureUtilizations for Premium P2 requiring features.

As already mentioned above, for this initial public preview release of the feature, only the Conditional access usage data is taken into consideration. Thus, under the p1FeatureUtilizations property we get the number of users that have been taking advantage of Conditional access policies (the generic version of feature, without any controls that enforce P2 requirements), whereas the p2FeatureUtilizations property gives us the number of users that have been subject to risk-based conditional access policies. For both the P1 and P2 insights, data is given for both regular (“member”) and Guest users.

Unfortunately, neither the Graph API nor the UI implementation of the insights gives you any information as to what the period for which said insights were generated is. Assuming Microsoft is keeping consistent with the rest of their reports and analytics on Entra ID side of things, I’d wager the last 30 days are covered, but I can be wrong on that. A quick stroll over the Entra sign-in logs seems to confirm this. But it also reveals a problem – the Guest user flagged in the p1FeatureUtilizations data is in fact my own user, accessing the Microsoft tenant.

Based on the data exposed within the sign-in log events for the past 30 days, I would also question the accuracy of the count of member users returned in the insight above. If we look at the User field, we do get six distinct entries, but one of them is a duplicate of my own account (which stems from the Guest login to the Microsoft tenant, as mentioned above). In fact, if we get the unique values based on the User ID property instead, or the UPN, we get five distinct entries, as it should be. Or at least this is the best analysis I can make based on the data at hand, as sadly the insights currently do not offer any way to “drill down” and reveal the individual users.



Moving on, we can obtain the usage insights data via application permissions. The example below uses an access token obtained via the client credentials flow, for an application with the required Reports.Read.All permission. Once the token is obtained, it is stored in the header variable and passed on to the request:

$uri = 'https://graph.microsoft.com/beta/reports/azureADPremiumLicenseInsight'
$gr = Invoke-WebRequest -Headers $authHeader -Uri $uri -Verbose -Debug
($gr.Content | ConvertFrom-Json)

@odata.context : https://graph.microsoft.com/beta/$metadata#reports/azureADPremiumLicenseInsight/$entity
entitledP1LicenseCount : 0
entitledP2LicenseCount : 5
entitledTotalLicenseCount : 5
p1FeatureUtilizations : @{conditionalAccess=; conditionalAccessGuestUsers=}
p2FeatureUtilizations : @{riskBasedConditionalAccess=; riskBasedConditionalAccessGuestUsers=}

If you recall the output from the Graph explorer example above, we get the exact same numbers. And here’s quick and dirty way to get the breakdown by license type:

$Report = ($gr.Content | ConvertFrom-Json)

$objUsage = [PSCustomObject][ordered]@{
"P1 usage (members)" = $Report.p1FeatureUtilizations.conditionalAccess.userCount
"P1 usage (guests)" = $Report.p1FeatureUtilizations.conditionalAccessGuestUsers.userCount
"P2 usage (members)" = $Report.p2FeatureUtilizations.riskBasedConditionalAccess.userCount
"P2 usage (guests)" = $Report.p2FeatureUtilizations.riskBasedConditionalAccessGuestUsers.userCount

P1 usage (members) P1 usage (guests) P2 usage (members) P2 usage (guests)
------------------ ----------------- ------------------ -----------------
                 6                 1                  0                 0

You can of course use the $select query parameter to fetch just the type of insights you care about. In fact, the two built-in reports within the UI both use this in the form $select=p2FeatureUtilizations,entitledP2LicenseCount.

And with that, we’ve covered all there is to cover about the new Microsoft Entra License Utilization Insights preview. While the idea of providing a report on “Premium” license utilization is welcomed, the current implementation leaves a lot to be desired. I would certainly love to see the feature offer some sort of a drill-down option and reveal the actual IDs of the users included in the usage counts. We can argue that procuring a sufficient number of licenses is enough to satisfy the licensing requirements, even if you do not assign them to the users in question, but in my experience, organizations do actually care about such data. If nothing else, providing user-level details will help clear out any confusion for the aforementioned “guest” count.

Providing some clarity to the period for which data is collected and presented in the insights would also help. And of course, expanding the insights to cover additional “premium” features would go a long way!

1 thought on “Obtaining Entra license utilization insights data via the Graph API

Leave a Reply

Your email address will not be published. Required fields are marked *

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