Reporting on Conditional Access policies in Microsoft 365

The Conditional Access endpoints have been available for a while in the Graph API, and while still in beta, they can be used to get a list of your CA policies or manage them. In this short article, we will explore how to build a report of any CA policies configured in the tenant and provide you with a proof-of-concept script.

First things first, as usual with Graph API calls, you need to obtain a token. You can use either the delegate permission or application permission model for that, and all you need is to include the Policy.Read.All scope. Once you have obtained a token, getting a list of policies is as easy as querying the /identity/conditionalAccess/policies/ endpoint (under /beta for now):

$CAs = Invoke-WebRequest -Headers $AuthHeader1 -Uri "" 

Some additional transformation of the output might be needed to get a meaningful report, featuring the different conditions and controls. Things like the name of the policy and its status are a non-brainer, but when it comes to the full list of conditions and actions supported, the output can be a bit ugly. The format I’ve chosen adds some readability and looks something like the below:


Now, this is after all a proof-of-concept, so some obvious quality of life improvements have been skipped. The output will feature tons of GUIDs, which you can replace with the actual app name, user UPN, group name, role name and so on. This is fairly straightforward when using the Graph API, as long as you have the necessary permissions to call the corresponding endpoints. So we can make a small addition to the script, which “converts” GUIDs to more readable identifiers, but it turn requires you to run it with an application that has Directory.Read.All permissions as well. The report is much easier to read now:


In the above, I have rearranged/hidden some columns for illustrative purposes. Even with those small tweaks, some GUIDs will remain, such as those corresponding to application IDs, or named locations. You can handle them in the same manner – run a query against the corresponding Graph endpoint, and as long as you have the necessary permissions, replace the result with a more readable value. I left this as an exercise for the reader 🙂

Note that the createdDateTime and modifiedDateTime properties are currently returned blank, as a known issue. Those values will be populated for newly created or modified policies though. The output will also fail to return any “baseline” policies, which is also a known issue/expected behavior.

Anyway, you can find the sample script over at my GitHub PowerShell repo. For additional details, you can always consult the official documentation.

1 thought on “Reporting on Conditional Access policies in Microsoft 365

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.