Microsoft Entra ID security

How to export Conditional Access policies in Entra ID

Export Conditional Access policies with Microsoft Graph PowerShell, review them in the Entra admin centre, or use Altivane's Conditional Access report for a workbook with each policy in words.

By the Published Updated

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.

Choose the method that fits the job
MethodBest fit
PowerShellEvery policy in a tenant as a CSV summary and a JSON file of the full settings.
Admin centreReading 1 policy's settings, or scanning the policy list.
AltivaneRecommended 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.Read.All; 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.

PowerShell
# Install once, if the modules are not already installed.
Install-Module Microsoft.Graph.Authentication, Microsoft.Graph.Identity.SignIns -Scope CurrentUser
PowerShell
$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.

PowerShell
# 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 10

Option 2

Review Conditional Access policies in the admin centre

  1. Sign in to the Microsoft Entra admin centre for the correct tenant.
  2. 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.
  3. Use the filter options at the top of the list to narrow it.
  4. Select a policy to open it, then read Assignments and Access controls: who and what it applies to, and what it grants or blocks.
  5. 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.

Common 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.Read.All 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.

Talk to us about Altivane

Questions, or pricing? Get in touch.

Contact us