How to Manage Conditional Access as Code – The Ultimate Guide

As you might have noticed, I’ve been updating and re-releasing my Conditional Access toolbox for the last couple of weeks. It is now easily accessible through the PowerShell Gallery and the source code is available on GitHub. Feel free to modify the tools to suit your needs.

This blog post summaries and concludes this work and explains my vision of zero trust Conditional Access management by treating your policies as code.

Conditional Access management in Visual Studio Code

Why manage Conditional Access as Code?

There are many valuable reasons for managing your Conditional Access policies as code. Everything you can put in code can easily be source controlled, version controlled and monitored. It is easy to backup your configuration, to rapidly release changes, and to roll-back in case of issues. You should manage Conditional Access as code because:

  • You can adopt a DevOps style of work around your zero trust security model (manage your code in Azure DevOps).
  • You can version control your policy design and roll-back to any previous state of configuration.
  • You can track who changed what.
  • You can deploy the exact same policy in multiple tenants.
  • You get policy documentation for free.
  • You can easily meet your backup goals.
  • You can restore your policy design in case of faulty configuration or sabotage.
  • You can rapidly roll-out parallell policy designs for testing and report-only mode scenarios.
  • You can share your policy design and knowledge with the Azure AD community.
  • Just to name a few!!


All the tools I’ve built around Conditional Access policy management is now included in one PowerShell module called DCToolbox.

Install the module from the PowerShell Gallery by running:

Install-Module DCToolbox

If you already installed it, update to the latest version by running:

Update-Module DCToolbox

When you have installed it, to get started, run:


Explore and copy script examples to your clipboard with:


The examples includes instructions, guidance, complete scripts and snippets. There is one called “Manage Conditional Access as code” containing all script examples in this blog post.

Microsoft Graph Permissions

Before running any of the Conditional Access related CMDlets, you first need to register a new application in your Azure AD and grant it the required Microsoft Graph Permissions according to the Register an Application in Azure AD section in this article. Remember to save your application ID (ClientID) and application secret (ClientSecret).

The required DELEGATED Graph Permissions for my Conditional Access tools are:

  • Policy.ReadWrite.ConditionalAccess
  • Policy.Read.All
  • Directory.Read.All
  • Agreement.Read.All
  • Application.Read.All

Also, the user running the CMDlets (the one who signs in when the authentication pops up) must have the appropriate permissions in Azure AD (Global Admin, Security Admin, Conditional Access Admin, etc).

Export/Backup Your Current Conditional Access Policy Design

A great way of getting started is to simply export your current Conditional Access policies. You can do this by running Export-DCConditionalAccessPolicyDesign. Change ClientID and ClientSecret to match your registered app before running.

# Export your Conditional Access policies to a JSON file for backup.
$Parameters = @{
    ClientID = ''
    ClientSecret = ''
    FilePath = 'C:\Temp\Conditional Access Backup.json'

Export-DCConditionalAccessPolicyDesign @Parameters

This will export all your Conditional Access policies to a standardised JSON file. You can easily import the same policy again with Import-DCConditionalAccessPolicyDesign.

Import Conditional Access Policy Design

When you have a JSON file with your desired configuration, you can import it with Import-DCConditionalAccessPolicyDesign.

# Import Conditional Access policies from a JSON file exported by Export-DCConditionalAccessPolicyDesign.
$Parameters = @{
    ClientID = ''
    ClientSecret = ''
    FilePath = 'C:\Temp\Conditional Access Backup.json'
    SkipReportOnlyMode = $false
    DeleteAllExistingPolicies = $false

Import-DCConditionalAccessPolicyDesign @Parameters

By default, the policies will be created in report-only mode but if you have already tested your policy design and are certain that it works, you can set SkipReportOnlyMode to $true to make them go live right away.

You can also delete all existing Conditional Access policies by setting DeleteAllExistingPolicices to $true. This is very powerful when you want to go all in and manage your Conditional Access as code. It will basically overwrite your implemented policy design with the new one in the JSON file. PLEASE USE THIS PARAMETER WITH CAUTION!!

Edit Conditional Access as Code

We’ve already mentioned that policies are exported and imported as JSON. Of course, this means that we can edit the JSON code with any text editor to modify policies or to create new ones.

I strongly recommend using Visual Studio Code for JSON editing. PowerShell does not export the prettiest JSON you’ve seen so the first thing I always do is letting Visual Studio Code format the JSON for me to make it more readable.

Each policy in the JSON file will look something like this:

    "displayName": "BLOCK - Legacy Authentication",
    "state": "enabled",
    "sessionControls": null,
    "conditions": {
        "userRiskLevels": [],
        "signInRiskLevels": [],
        "clientAppTypes": [
        "platforms": null,
        "locations": null,
        "deviceStates": null,
        "devices": null,
        "clientApplications": null,
        "applications": {
            "includeApplications": [
            "excludeApplications": [],
            "includeUserActions": []
        "users": {
            "includeUsers": [
            "excludeUsers": [],
            "includeGroups": [],
            "excludeGroups": [
            "includeRoles": [],
            "excludeRoles": []

You can read about the syntax and all possible settings in the Microsoft Graph documentation if your’re interested. I use the beta API since no Conditional Access preview features are available in the v1.0 API (and there are many important preview features we want to use).

I also recommend installing the Visual Studio Code plugin Json Editor. This makes it really easy to make changes to your Conditional Access policy design and to move policies around if you want them in a preferred order in the portal.

Create an Easy-to-Read Conditional Access Policy Design Report in Excel

Finally, you can use New-DCConditionalAccessPolicyDesignReport to create a nice Excel report of your current Conditional Access policy design. I believe that this is the easiest way to get an overview of a complex Conditional Access implementation and this is something I always do when I come across a new tenant.

# Export Conditional Access policy design report to Excel.
$Parameters = @{
    ClientID = ''
    ClientSecret = ''

New-DCConditionalAccessPolicyDesignReport @Parameters

When the script completes, Excel will open the new report. To fine tune its appearance, press CTRL+A to select all cells, wrap the text and make it stay on top (see below). This will produce the same format as in the example.

The report will look something like this:


This is the conclusion of my effort to bring easy Conditional Access code management to the community. Of course, I will continue to improve the tools and release new ones, but this is the very important foundation.

I will also continue to provide my Conditional Access baseline, from now on as a JSON file that can be imported with Import-DCConditionalAccessPolicyDesign.

To learn more about the Conditional Access tools used, run:

Get-Help Export-DCConditionalAccessPolicyDesign -Full
Get-Help Import-DCConditionalAccessPolicyDesign -Full
Get-Help New-DCConditionalAccessPolicyDesignReport -Full

I hope you find all of this useful and inspiring and I hope it will help you on your zero trust journey in the Microsoft cloud!

Please follow me here, on LinkedIn and on Twitter!