AccessPilot Knowledge Base

Contents › Reference

Microsoft Graph conditionalAccessPolicy schema

Every condition, grant and session control, and the review heuristics keyed to each.
Published by Urbannerd Consulting · Reviewed 2026-07-29

Microsoft Graph conditionalAccessPolicy — schema reference

Endpoint: GET https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies

Named locations: GET .../identity/conditionalAccess/namedLocations

This is the agent's canonical vocabulary for policy review. When a user pastes JSON, parse

against this. When a user describes a portal screen, map their words onto these fields so

findings are precise.

Top-level shape


{
  "id": "<guid>",
  "displayName": "<policy name>",
  "createdDateTime": "...",
  "modifiedDateTime": "...",
  "state": "enabled | disabled | enabledForReportingButNotEnforced",
  "conditions": { ... },
  "grantControls": { ... },
  "sessionControls": { ... }
}

state values map to the portal as: enabled = On, disabled = Off,

enabledForReportingButNotEnforced = Report-only.

conditions


"conditions": {
  "users": {
    "includeUsers": ["All" | "None" | "GuestsOrExternalUsers" | "<guid>"],
    "excludeUsers": ["<guid>"],
    "includeGroups": ["<guid>"],
    "excludeGroups": ["<guid>"],
    "includeRoles": ["<roleTemplateId>"],
    "excludeRoles": ["<roleTemplateId>"],
    "includeGuestsOrExternalUsers": { "guestOrExternalUserTypes": "...", "externalTenants": {...} },
    "excludeGuestsOrExternalUsers": { ... }
  },
  "applications": {
    "includeApplications": ["All" | "None" | "Office365" | "<appId>"],
    "excludeApplications": ["<appId>"],
    "includeUserActions": ["urn:user:registersecurityinfo" | "urn:user:registerdevice"],
    "includeAuthenticationContextClassReferences": ["c1"],
    "applicationFilter": { "mode": "include|exclude", "rule": "..." }
  },
  "clientAppTypes": ["all" | "browser" | "mobileAppsAndDesktopClients" | "exchangeActiveSync" | "other"],
  "platforms": { "includePlatforms": ["windows","macOS","iOS","android","linux","all"], "excludePlatforms": [...] },
  "locations": { "includeLocations": ["All" | "AllTrusted" | "<guid>"], "excludeLocations": ["AllTrusted" | "<guid>"] },
  "devices": { "deviceFilter": { "mode": "include|exclude", "rule": "device.isCompliant -eq True" } },
  "signInRiskLevels": ["low","medium","high","none"],
  "userRiskLevels": ["low","medium","high","none"],
  "servicePrincipalRiskLevels": ["low","medium","high","none"],
  "authenticationFlows": { "transferMethods": "deviceCodeFlow,authenticationTransfer" },
  "insiderRiskLevels": "minor | moderate | elevated"
}

Notes that matter in review:

service principals — those need workload identity CA.

but-inactive admins are not in scope. This surprises almost everyone.

authentication signature . One without the other is an incomplete block.

scoped to Office365 still leaves admin portals and the Azure Service Management API

reachable — the benchmark guidance concern.

grantControls


"grantControls": {
  "operator": "AND | OR",
  "builtInControls": ["block","mfa","compliantDevice","domainJoinedDevice",
                      "approvedApplication","compliantApplication","passwordChange","unknownFutureValue"],
  "customAuthenticationFactors": [],
  "termsOfUse": ["<guid>"],
  "authenticationStrength": { "id": "<guid>", "displayName": "...", "allowedCombinations": [...] }
}

operator is the highest-value field in the entire schema.

["mfa","compliantDevice"] with operator: "OR" means **a compliant device satisfies the

policy without any MFA**. This is the benchmark guidance warning and the most common serious

misconfiguration the agent will encounter. The correct construction is two policies, which

combine as AND across policies.

block is exclusive — it cannot be meaningfully combined with grant controls.

Authentication strength combination values include fido2, windowsHelloForBusiness,

x509CertificateMultiFactor, password,microsoftAuthenticatorPush, temporaryAccessPassOneTime

and others. Phishing-resistant is the built-in strength whose allowed combinations are

exactly windowsHelloForBusiness, fido2, x509CertificateMultiFactor .

Any valid authenticationStrength.id also satisfies a plain MFA requirement — strengths

are strictly stronger.

sessionControls


"sessionControls": {
  "applicationEnforcedRestrictions": { "isEnabled": true },
  "cloudAppSecurity": { "isEnabled": true, "cloudAppSecurityType": "monitorOnly|blockDownloads|mcasConfigured" },
  "signInFrequency": {
    "isEnabled": true,
    "type": "days | hours",
    "value": 7,
    "authenticationType": "primaryAndSecondaryAuthentication | secondaryAuthentication",
    "frequencyInterval": "timeBased | everyTime"
  },
  "persistentBrowser": { "isEnabled": true, "mode": "always | never" },
  "continuousAccessEvaluation": { "mode": "strictLocation | disabled" },
  "secureSignInSession": { "isEnabled": true },
  "disableResilienceDefaults": false
}

.

skew tolerance.

an Entra outage. Rarely intended; flag it.

namedLocations

Two types, distinguished by @odata.type:


// microsoft.graph.ipNamedLocation
{ "displayName": "...", "isTrusted": true, "ipRanges": [ { "@odata.type": "#microsoft.graph.iPv4CidrRange", "cidrAddress": "203.0.113.0/24" } ] }

// microsoft.graph.countryNamedLocation
{ "displayName": "...", "countriesAndRegions": ["ZA","GB"], "includeUnknownCountriesAndRegions": false,
  "countryLookupMethod": "clientIpAddress | authenticatorAppGps" }

Only IP named locations can be trusted. countryNamedLocation has no isTrusted

property. This is why country-based designs cannot use the All trusted locations option

.

Review heuristics keyed to the schema

Pattern in JSONWhat to say
excludeUsers empty and excludeGroups empty on an enforcing policyNo break-glass exclusion → Critical
operator: "OR" with mfa plus a device controlCompliant device bypasses MFA → Critical
includeApplications not ["All"] on an MFA policyAdmin portals reachable → High (benchmark guidance/2)
state: "enabled" with no evidence of a report-only periodUnmeasured blast radius → High
signInRiskLevels or userRiskLevels populatedRequires P2 across the scoped population
clientAppTypes has exchangeActiveSync without other, or vice versaIncomplete legacy block → Medium
secureSignInSession enabled with clientAppTypes including browserUnsupported on browsers → Medium
disableResilienceDefaults: trueOutage backstop removed → Medium
excludeGroups referencing a group of unknown typeAsk whether it is role-assignable → potentially Critical

Caveat

This schema evolves — Microsoft adds conditions and controls regularly, and preview

properties appear on beta before v1.0. Treat an unrecognised property as *newer than

this file*, not as invalid, and say so rather than telling the user their export is wrong.

[VERIFY] against the current conditionalAccessPolicy resource documentation when a

field is decisive to a finding.