Calculating the Licensing Requirement for Entra Conditional Access Policies

Figuring Out Who Needs Entra P1 Licenses

In the discussion about the licensing gap highlighted in the Entra admin center between the use of conditional access policies and accounts with Entra P1 or P2 licenses, I made the point that the number of licenses owned by the tenant might be more than the actual usage as reported by Entra license insights and confirmed by analysis of Entra sign-in audit records. It might be possible to bring everything back into balance by reassigning licenses to the accounts which actually use conditional access.

The PowerShell code included in the article shows how to find the user accounts that have used conditional access policies during sign-ins over the last 30 days. However, that’s not quite the same as satisfying Microsoft licensing requirements.

Microsoft’s Licensing Requirements

The requirements for conditional access policies are a little fuzzy. The documentation simply says, “Using this feature requires Microsoft Entra ID P1 licenses.” Lawyers can debate what “using” means. A clue comes from the product usage insight, which defines conditional access usage as: “the number of unique users with at least one Conditional Access policy evaluated during the measurement period.” I can find no other Microsoft statement with a more precise definition for the licensing requirement. The recent licensing gap notifications also do not explain how the licensing scope is calculated.

In any case, it’s wise to take a practical approach to these matters. If a tenant has deployed conditional access policies to protect connections, it is likely that most if not all user (member) accounts need to be licensed. Administrators will exclude some accounts from conditional policy processing, like break glass accounts, but the norm for a user account doing regular work is that they will be subject to conditional access policies for purposes such as enforcement of multifactor authentication and securing access to high-priority apps.

In that context, the target set for licensing is defined as user accounts that are not disabled and have at least one assigned license. This filter excludes disabled accounts such as those used for shared mailboxes, guest accounts covered through MAU-based licensing, and dormant directory objects that have no access to Microsoft services. It should find the set of accounts that connect to Microsoft services, which are therefore likely to be processed by conditional access policies.

With the target set defined, we can think about checking the licensing situation for the active conditional access policies within a tenant. This can be done by checking the included and excluded conditions defined for policies. Some policies will apply to all users with perhaps exclusions for break glass accounts. Some policies will be more specific about the users and groups that come within their scope.

Processing Conditional Access Policies

The Get-MgIdentityConditionalAccessPolicy cmdlet can find the set of active policies (those currently enabled):

[array]$Policies = Get-MgIdentityConditionalAccessPolicy -All -Filter "state eq 'enabled'"

See this article for more information about using the Microsoft Graph PowerShell SDK to manage conditional access policies.

After finding the policies, it’s a matter of analyzing the users, groups, and roles covered by each policy. These values are held in the Conditions.Users property for a policy. The aim is to determine the set of accounts covered by each policy and combine the sets together into an array of unique account identifiers. The set of included and excluded accounts for a policy can be found with:

[array]$PolicyIncludedUsers = $Policy.Conditions.Users.IncludeUsers
[array]$PolicyExcludedUsers = $Policy.Conditions.Users.ExcludeUsers

Some complications exist, such as when policy scope is set by membership of groups (remembering to use transitive membership) or the membership of directory roles. In practice, directory roles like Global administrator are often used to target privileged accounts, so role membership must be considered when calculating the effective scope of Conditional Access policies. These requirements are met by using the Get-MgGroupTransitiveMemberAsUser and Get-MgDirectoryRoleMember cmdlets to fetch the identifiers of members and include them in the mix.

License Validation

After processing all the policies, we can find any product subscriptions that include the Entra P1 service plan:

# Fetch licensed users with a license that includes an Entra P1 or P2 service plan
$EntraPlan1 = "41781fb2-bc02-4b7c-bd55-b576c07bb09d"
$EntraPlan2 = "eec0eb4f-6444-4f95-aba0-50c24d67f998"
[array]$EntraSkus = Get-MgSubscribedSku -All | Where-Object {
    $_.ServicePlans.ServicePlanId -contains $EntraPlan1 -or
    $_.ServicePlans.ServicePlanId -contains $EntraPlan2 }  | Select-Object SkuId, SkuPartNumber, PrepaidUnits

And then find the set of user accounts holding a license with an Entra P1 or P2 service plan (P2 confers the rights contained in a P1 license):

[array]$LicensedP1Users = Get-MgUser -ConsistencyLevel Eventual -CountVariable Licenses -PageSize 500 -Property Id, displayName, userPrincipalName, assignedPlans -Filter "(assignedPlans/any(s:s/servicePlanId eq $EntraPlan2) or assignedPlans/any(s:s/servicePlanId eq $EntraPlan1)) and userType eq 'Member' and accountEnabled ne false"

We can’t use this information immediately because the presence of a service plan in the license information maintained for an account might be a disabled plan due to the removal of a license. We need to check that the service plan is enabled.

This code checks each user to validate if the Entra P1 service plan is enabled and builds a list of user accounts with Entra P1 enabled:

$ListCALicensedUsers = [System.Collections.Generic.List[object]]::new()
ForEach ($P1User in $LicensedP1Users) {
   $CheckPlan = $P1User.assignedPlans | Where-Object {$_.ServicePlanId -eq $EntraPlan1} | Select-Object -ExpandProperty CapabilityStatus
   If ($CheckPlan -eq "Enabled") {
        $ReportLine = [PSCustomObject]@{
            UserId          = $P1User.Id
            DisplayName     = $P1User.DisplayName
            UserPrincipalName = $P1User.UserPrincipalName
        }
        $ListCALicensedUsers.Add($ReportLine)
   }    
}

The next step is to calculate the set of users who don’t have a P1 or P2 license but need one because they are found within a policy scope:

# Get the set of users who aren't licensed for Entra P1 or P2 but are within the scope for at least one CA policy
[array]$UsersNeedingEntraP1 = $TotalUsersFound | Where-Object { $_ -notin $ListCALicensedUsers.UserId }

All processing is done using account identifiers (GUIDs). This is good because the identifiers are immutable, but a step is needed to translate the GUIDs into user-friendly information like display names. An early step at the start of the script fetched the set of licensed users. To avoid the need to retrieve user data again, we create an array based on the set of identifiers for accounts needing Entra P1 licenses:

[array]$UsersWithoutEntraP1Licenses = $Users | Where-Object { $_.Id -in $UsersNeedeingEntraP1 } | Select-Object DisplayName, UserPrincipalName, Id

The script finishes by generating an Excel workbook (if the ImportExcel module is available – Figure 1) or CSV file containing details of the users who need Entra P1 licenses. Alternatively, accounts can be excluded from CA policies to reduce the licensing requirement.

Listing accounts that should have Entra P1 licenses for conditional access policies.
Figure 1: Listing accounts that should have Entra P1 licenses for conditional access policies

Running the Code

You can download the full script from the Microsoft 365 for IT Pros GitHub repository. The code uses the Microsoft Graph PowerShell SDK and should be run in an interactive session when signed into an administrator account with access to policies, groups, and user accounts. Alternatively, use app-only authentication with an app assigned the necessary permissions.

I do not claim that the script proves tenant compliance with Microsoft licensing requirements. Coding against imprecise information is always difficult, and Microsoft does not publish a precise definition of Conditional Access licence consumption. What it does do is identify the enabled member accounts that fall within the effective scope of active Conditional Access policies and compares that set against accounts with Entra P1 or P2 licenses. It seems like a reasonable place to start when investigating a reported licensing gap.

I’m sure that some will find ways to improve the code, such as adding a section to handle the calculation of an Entra P2 licensing requirement. In any case, have fun with the PowerShell!


Need help to write and manage PowerShell scripts for Microsoft 365, including Azure Automation runbooks? Get a copy of the Automating Microsoft 365 with PowerShell eBook, available standalone or as part of the Microsoft 365 for IT Pros eBook bundle.

3 Replies to “Calculating the Licensing Requirement for Entra Conditional Access Policies”

  1. Hi Tony,

    thank you for your insights!
    Currently I have the question (which Microsoft doesn’t want to answer us), if we also have to license Agent 365 for all users, if all users can profit from (at least) one agent, which is also secured by a conditional access policy, which is recommended by several MS partners of ours as a security measure??
    This would have a huge impact on our budget – but from what I could find, there’s no way around this requirement (if agents are protected via conditional access)?

    Thanks,
    Thomas

    1. According to https://learn.microsoft.com/en-us/entra/identity/conditional-access/agent-id:

      “Conditional Access for agents requires Microsoft Entra ID P1 or P2 and a Microsoft Agent 365 license for each user. Enforcement of Agent 365 licensing is coming soon. Network controls for agents require Microsoft Entra Internet Access. For more information, see What is Microsoft Entra Agent ID.”

      I read this to mean that when users benefit from agent processing, those agents must be licensed. The language isn’t very precise, so I followed the normal guideline of when someone receives benefit from a Microsoft feature, they must be licensed to use that feature.

      However, in Microsoft’s June 2026 licensing changes. Microsoft introduced dedicated service plans:

      ENTRA_CONDITIONAL_ACCESS_FOR_AGENTS
      ENTRA_ID_PROTECTION_FOR_AGENTS

      and added them to Microsoft Agent 365 and Microsoft 365 E7. Sources reporting the Microsoft announcement state that customers using Conditional Access for agents must have the appropriate Agent 365/E7 licensing. If your users have E7, they have P2, and don’t need any additionl licensing for CA for agents.

      Putting everything together, I think we can say:

      Conditional Access for agents requires Entra ID P1 or P2 plus Microsoft Agent 365 licensing. Microsoft states that a Microsoft Agent 365 license is required “for each user,” but Microsoft has not yet published detailed guidance explaining exactly how the licensing scope is calculated

      1. Hi Tony,

        thank’s a lot for your swift answer – that gives me confidence for the next budget round…!

Leave a Reply

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