To export Conditional Access policies, read them with Get-MgIdentityConditionalAccessPolicy and write a CSV of the settings you need, plus a JSON file of every setting. A policy names its users, groups and roles by ID, so the export holds IDs, not names. It shows the configuration, not the sign-ins the policies affected.
| Method | Best fit |
|---|---|
| PowerShell | Every policy in a tenant as a CSV summary and a JSON file of the full settings. |
| Admin centre | Reading 1 policy's settings, or scanning the policy list. |
| Altivane | Recommended for recurring reviews, with names in place of IDs and the policies not enforced listed. |
Before you start
Use an account in one of these roles: Security Reader, Global Reader, Security Administrator or Conditional Access Administrator. Conditional Access needs Microsoft Entra ID P1, or Microsoft 365 Business Premium; if the licence lapses, policies stay and can be viewed but not updated. The PowerShell example requests Policy.; your organisation may require administrator consent.
The export is the policies as they are now. To see which policies applied to a sign-in, read the Conditional Access tab of that sign-in in the Entra sign-in logs. The examples read and export; they change nothing.
Option 1
Export Conditional Access policies with PowerShell
Install the modules once, then connect and read every policy. The script writes a CSV with 1 row per policy and a JSON file with every setting. -All follows the paging, so no policy is missed.
# Install once, if the modules are not already installed.
Install-Module Microsoft.Graph.Authentication, Microsoft.Graph.Identity.SignIns -Scope CurrentUser$ErrorActionPreference = 'Stop'
$csv = './conditional-access-policies.csv'
$json = './conditional-access-policies.json'
Connect-MgGraph -Scopes 'Policy.Read.All' -NoWelcome
try {
$policies = @(Get-MgIdentityConditionalAccessPolicy -All)
if ($policies.Count -eq 0) {
Write-Output 'The tenant has no Conditional Access policies.'
} else {
$join = { param($values) @($values) -join '; ' }
$utc = {
param($date)
if ($date) { $date.ToUniversalTime().ToString('yyyy-MM-dd HH:mm') }
}
$rows = foreach ($policy in ($policies | Sort-Object DisplayName)) {
$users = $policy.Conditions.Users
$apps = $policy.Conditions.Applications
$grant = $policy.GrantControls
[pscustomobject]@{
DisplayName = $policy.DisplayName
State = $policy.State
CreatedUtc = & $utc $policy.CreatedDateTime
ModifiedUtc = & $utc $policy.ModifiedDateTime
IncludeUsers = & $join $users.IncludeUsers
ExcludeUsers = & $join $users.ExcludeUsers
IncludeGroups = & $join $users.IncludeGroups
ExcludeGroups = & $join $users.ExcludeGroups
IncludeRoles = & $join $users.IncludeRoles
ExcludeRoles = & $join $users.ExcludeRoles
IncludeApplications = & $join $apps.IncludeApplications
ExcludeApplications = & $join $apps.ExcludeApplications
GrantControls = & $join $grant.BuiltInControls
GrantOperator = $grant.Operator
AuthenticationStrength = $grant.AuthenticationStrength.DisplayName
Id = $policy.Id
}
}
$rows | Export-Csv -Path $csv -NoTypeInformation -Encoding utf8
ConvertTo-Json -InputObject $policies -Depth 10 | Set-Content -Path $json -Encoding utf8
Write-Output "$($policies.Count) policies exported to $csv and $json."
}
} finally {
Disconnect-MgGraph | Out-Null
}The CSV keeps each policy's name, state (enabled, disabled or enabledForReportingButNotEnforced), created and modified times in UTC, who it includes and excludes, the applications it covers and what it grants. Users, groups and roles are IDs, apart from All, None and GuestsOrExternalUsers. The JSON file holds the rest: platforms, locations, risk levels and session controls. ConvertTo-Json stops 2 levels down by default, so the script sets -Depth 10.
Check a single policy
Reconnect with Connect-MgGraph, then read 1 policy by its name. The main export above disconnects when it finishes.
# Run while connected to Microsoft Graph. Replace the example policy name.
$name = 'Require multifactor authentication for administrators'
Get-MgIdentityConditionalAccessPolicy -All |
Where-Object { $_.DisplayName -eq $name } |
ConvertTo-Json -Depth 10Option 2
Review Conditional Access policies in the admin centre
- Sign in to the Microsoft Entra admin centre for the correct tenant.
- Go to Entra ID > Conditional Access > Policies. The list holds every policy, report-only ones included, and policies Microsoft manages show Microsoft in the Created by column.
- Use the filter options at the top of the list to narrow it.
- Select a policy to open it, then read Assignments and Access controls: who and what it applies to, and what it grants or blocks.
- Leave without saving. The policy opens in its editor, so change nothing, including Enable policy.
This suits reading 1 or 2 policies, or checking a policy before you change it. Each policy opens on its own, so for a list to sort, keep and compare, export with PowerShell or use Altivane.
Option 3 ยท Recommended for recurring reviews
Report on Conditional Access policies with Altivane
- Open Altivane and choose the tenant.
- Build the tenant's documents with the Conditional Access scorecard report in full to include policy details; Summary keeps only the counts.
- Open the tenant's Excel workbook and read Policy Overview, with 1 line per policy and its State, Targets, Exclusions, Grant and Modified, then Policy Details for every setting and its Id.
- Review Policies Not Enforced, Policies Referencing Deleted Objects and Enabled All-User Policies Without Exclusions first, and Conditional Access Summary for the counts.
Altivane names the users, groups, roles, applications and locations a policy refers to, and labels an ID it cannot find "not found, possibly deleted". Policy Overview and Policy Details are in the Word report too; the 3 findings tables are in the workbook only. The scorecard rates policies not enforced and policies referencing deleted objects, with Warning at 1 and Critical at 3 to start. The build also writes the tenant's Word report.
Contact usCommon questions
Why does the export show IDs instead of names?
Microsoft Graph returns the IDs a policy holds. Look an ID up in the admin centre, or read the names in Altivane's Policy Overview and Policy Details.
Does a policy that requires MFA cover every account?
No. A policy covers the users, groups and roles it includes, less those it excludes, and only the applications it targets. Check the exclusions for accounts left out by mistake. Whether people have registered an MFA method is a separate question: see how to find users without MFA.
Why does the script return an error or no policies?
Check the role and the permission first: the signed-in account needs 1 of the roles above, and Policy. needs consent. A tenant with no policies returns an empty list, and the script says so.
Microsoft references
Technical references checked on 5 October 2026. The example scripts have been reviewed and syntax checked; they have not been run against a live tenant.