Microsoft 365 Identity

Gating Microsoft 365 with Endpoint Conditional Access: Compliance Policies, Device Filters, and Require-Compliant Enforcement

The strongest Conditional Access control most tenants under-use is “require a compliant or hybrid-joined device.” Multi-factor authentication proves who is signing in; the compliant-device grant proves what they sign in from — a corporate, managed, patched, encrypted endpoint rather than an unmanaged laptop in an internet café. It is the single highest-signal control in a Zero Trust posture because it moves the trust boundary from “a password plus a phone” to “a machine your organisation continuously evaluates.” It is also the control that generates the most self-inflicted outages, because three independent systems — Intune, Entra ID, and Conditional Access — must agree on a device’s state, asynchronously, before anyone is let in, and each one has a default that quietly makes the grant either toothless or a lockout.

This guide builds the full endpoint-gating stack end to end and then teaches you to debug it. You will author an Intune compliance policy (every setting class, the actions-for-noncompliance schedule that is your grace period, and the Defender for Endpoint risk connector), understand exactly how isCompliant flows from Intune onto the Entra device object and how Conditional Access reads it at token time, build the require-compliant and compliant-OR-hybrid grants correctly for a mixed estate, scope them with filters for devices (rules, attributes, the include/exclude trap), split managed desktops from personal phones with a parallel app-protection policy, and stage the whole thing through report-only so a bad grant never reaches production blind. The centrepiece is the troubleshooting playbook for the ticket every endpoint admin gets: “my device is Compliant in Intune but Conditional Access says it isn’t.”

By the end you will treat the compliant-device grant not as a scary switch but as an engineering system with a known state machine, a known set of failure modes, and a known diagnostic for each. You will know why a device that shows green in the Intune portal can still be blocked, why the “no policy assigned = Compliant” tenant default silently disarms your entire estate, why Require compliant on a hybrid-joined-but-not-enrolled fleet blocks all of it, and exactly which Graph query, sign-in log field or registry key confirms each. Knowing which within minutes is the difference between a five-minute fix and a tenant-wide checkout outage during a flash sale.

What problem this solves

Identity-only Conditional Access — MFA plus maybe a risk check — leaves a gaping hole: a valid user with valid credentials on a compromised or unmanaged device sails straight into Microsoft 365. Token theft, adversary-in-the-middle phishing that captures the post-MFA session cookie, a personal Windows machine with no disk encryption and disabled Defender, a contractor’s home PC syncing your entire SharePoint library to an unencrypted disk — none of these are stopped by MFA. They are stopped by requiring the sign-in to come from a device your organisation manages and continuously evaluates for health. That is what the compliant-device grant does, and it is the concrete mechanism behind the Zero Trust maxim “verify explicitly, assume breach.”

What breaks with it, when built carelessly, is worse than the hole it closes. The device-compliance grant is uniquely dangerous among CA controls because the accounts most likely to need emergency access — break-glass admins, automation identities — are the least likely to be signing in from an enrolled, compliant device. Flip Require compliant on “All cloud apps” with no break-glass exclusion and you lock every administrator out of the very portal needed to undo it. Set the “mark noncompliant” schedule to zero days during rollout and you block every device that is briefly remediating. Leave the tenant default at “no policy assigned = Compliant” and unmanaged devices sail through a grant you believe is enforcing. Confuse compliant (needs Intune) with hybrid-joined (does not) and you block an entire fleet of domain-joined PCs that were never enrolled.

Who hits this: every organisation moving from “MFA everywhere” to real device-based Zero Trust — which in 2026 is most of them, pushed by cyber-insurance requirements, regulatory mandates, and the reality that token theft has made “the user proved who they are” insufficient. It bites hardest on mixed estates mid-migration (cloud-managed laptops next to legacy hybrid-joined desktops), on BYOD-heavy organisations (personal phones that will never enrol), and on anyone who treats the compliant grant as a checkbox rather than a three-system state machine. The fix is almost never “loosen the policy” — it is “understand which of the three systems disagrees about the device, and why.”

To frame the whole field before the deep dive, here is the layered model every later section refines — the three systems, what each one owns, and the failure it causes when it is wrong:

Layer What it owns The signal it produces Failure when misconfigured Who typically owns it
Entra device registration The device object and its trustType (registered / hybrid / joined) The object CA reads; existence + join type No object → no device grant can ever pass Identity / endpoint team
Intune enrolment + compliance Evaluating the device against a compliance policy isCompliant (true/false) stamped onto the Entra object Not enrolled, or policy fails → blocked; “no policy = compliant” default → toothless Endpoint / Intune team
Defender for Endpoint Continuous machine risk scoring A risk level (Low/Med/High) fed into compliance Connector not wired → risk rule never evaluates Security team
Conditional Access The grant decision at sign-in Allow / block / require, per policy Wrong grant type, no break-glass exclusion, “All apps” scope → lockout Identity team
The device platform (OS) Broker/WAM, PRT, certificate that presents the state The device identity in the token request Missing PRT, broken WAM/broker → “device not compliant” on a compliant device OS / endpoint team

Learning objectives

By the end of this article you can:

Prerequisites & where this fits

You should already understand Conditional Access fundamentals: that a CA policy is an if-then statement (assignments: users + target resources + conditions → access controls: grant/session), that policies are additive and evaluated together, and that a blocked grant is the union of every applicable policy. You should know what Intune enrolment is (the device is MDM-managed by Intune, receiving policy and reporting inventory), the three Entra device join types (Entra registered / hybrid joined / Entra joined), and how to run Microsoft Graph PowerShell (Connect-MgGraph) and read JSON. Familiarity with managed identities, RBAC, and basic Windows/macOS/iOS/Android device concepts helps.

This sits in the Identity & Endpoint track, at the intersection of Conditional Access and Intune. It assumes the CA design fundamentals from Conditional Access at Scale: Personas & Authentication Context and the break-glass hygiene from Entra Break-Glass Emergency Access, Monitoring & Governance — read that one first, because a device grant without a break-glass exclusion is the fastest way to lock yourself out. It pairs tightly with Intune Filters: Assignment Targeting & Ring Deployment (compliance assignment scoping) and Intune MAM: App Protection Without Enrolment (BYOD), which is the other half of this design — the mobile grant that governs personal phones while the compliant grant governs desktops. The Defender risk half connects to Entra ID Protection: Risk-Based Policies, Tuning & Investigation (the user-risk analogue of the device-risk signal used here).

A quick map of who confirms what during an incident, so you call the right person fast:

Layer What lives here Who usually owns it Failure classes it can cause
Entra device object trustType, isCompliant, isManaged Identity team Grant blocked (no object / wrong join type / stale bit)
Intune compliance The policy, evaluation, actions schedule Endpoint / Intune team Device shows noncompliant; grace whiplash
Defender for Endpoint Machine risk score + connector Security team Risk rule never evaluates; high risk blocks unexpectedly
Conditional Access The grant + filter + scope Identity team Lockout; toothless grant; filter excluded the device
The client OS / broker PRT, WAM/broker, device certificate OS / endpoint team “Not compliant” on a compliant device (missing PRT)
Tenant defaults “No policy = compliant”, validity period Endpoint team Silent disarm; whole-fleet ageing to noncompliant

Core concepts

Five mental models make every later diagnosis obvious.

Three independent pieces must line up, in order. A “managed” device is allowed in only when all three of these are true, and they are produced by three different systems on three different schedules. First, a device registration state exists in Entra ID — the device object carries a trustType: Entra registered (BYO / workplace-joined), Entra hybrid joined (on-prem AD-joined and synced to Entra), or Entra joined (cloud-native, joined directly to Entra). No object, and no device grant can ever pass — there is nothing for CA to read. Second, a compliance state exists — Intune has enrolled the device, evaluated it against a compliance policy, and stamped isCompliant = true/false onto that same Entra device object. Third, the CA grantRequire device to be marked as compliant and/or Require Microsoft Entra hybrid joined device — reads the object at sign-in and decides. The order matters: registration is upstream of compliance, which is upstream of the grant.

Compliant needs Intune; hybrid-joined does not. This is the single most important fact and the number-one cause of “my domain PCs are blocked” tickets. The compliant grant requires the device to be Intune-enrolled and evaluated — Intune is the only thing that writes isCompliant. The hybrid-joined grant only requires the device to be hybrid-joined (present in on-prem AD, synced to Entra with trustType = ServerAd) and does not need Intune at all. If you flip Require compliant on a fleet of hybrid-joined machines that were never enrolled in Intune, every one of them is blocked, because none of them has ever had isCompliant set to true. For a mixed estate mid-migration, the answer is compliant OR hybrid-joined — cloud-managed machines pass on compliance, legacy domain machines on hybrid join, nothing breaks while you migrate.

Compliance evaluation is asynchronous, and CA reads a snapshot. The chain — device checks in to Intune → Intune evaluates the policy → Intune writes isCompliant to the Entra object → CA reads the object at the next sign-in / token request — is not instant at any hop. Compliance runs on the Intune check-in cycle (minutes to a few hours), not the moment a setting changes. CA evaluates the device object as it exists at token time; even after isCompliant flips, an existing token carries the old decision until the session refreshes or the user re-authenticates. Understanding this lag prevents most “why is it still blocked” confusion — the systems are eventually consistent, not immediately consistent.

The compliance bit ages, and stale means noncompliant. A device that stops checking in does not stay “compliant forever.” The Compliance status validity period (a tenant setting, e.g. 30 days) means a device that has not reported in that window has its isCompliant reverted to false on the Entra object — even if the local Intune client still shows green from its last successful evaluation. This is the subtlest production failure: a proxy blocks the Intune check-in endpoints, devices go quiet, the validity window expires, and CA starts blocking machines whose local status looks fine. Nominally compliant and actively checking in are different things, and CA reads the latter.

The device state must be presented in the token request, and that is the OS’s job. For CA to see a device as compliant, the client must attach a device identity to the sign-in — on Windows via the Primary Refresh Token (PRT) and the Web Account Manager (WAM) broker; on macOS via the Microsoft Enterprise SSO plug-in and the device’s registration; on iOS/Android via the Microsoft Authenticator / Company Portal broker. If the browser or app doesn’t use the broker, or the PRT is missing/expired, the token request carries no device state, and CA sees “unknown device” → not compliant → blocked, on a device that is perfectly compliant in Intune. A huge fraction of “device not compliant” tickets are this: the compliance is real, but the presentation of it failed at the client.

The vocabulary in one table

Before the deep sections, pin down every moving part. The glossary at the end repeats these for lookup; this table is the mental model side by side:

Concept One-line definition Where it lives Why it matters to the grant
Device object The Entra representation of a device Entra ID directory The thing CA reads; no object → no grant
trustType The join type of the device On the device object Chooses which grant (compliant vs hybrid) can apply
isCompliant The compliance bit Intune stamps On the device object The exact bit the compliant grant evaluates
Compliance policy Pass/fail rules + noncompliance actions Intune Produces isCompliant
Actions for noncompliance The schedule of what happens, and when Intune policy The “mark noncompliant” delay is the grace period
Compliance status validity How long a state stays valid without check-in Intune tenant setting Expiry ages isCompliant to false
MDE risk signal The machine risk score from Defender Defender ↔ Intune connector A compliance rule (“at or under Medium”)
Require compliant grant CA control needing isCompliant = true CA policy grant Needs Intune enrolment
Require hybrid-joined grant CA control needing trustType = ServerAd CA policy grant Does not need Intune
Filter for devices Rule over device attributes to scope a policy CA policy assignment Includes/excludes by device, not user
Extension attribute One of 15 writable tags on the device object Device object (via Graph) The tagging system filters key off
PRT Primary Refresh Token proving device state Windows client (WAM) Missing → device state not presented → blocked
Report-only A policy that evaluates but doesn’t enforce CA policy state The safe staging mode before enforcement

The device-based access model in depth

Everything downstream depends on getting the object model right, so start here. The Entra device object is the anchor; it is created when a device is registered, and it carries the two fields the grant cares about — trustType (how it joined) and isCompliant (whether Intune says it passes). A device can be registered without being enrolled (an object exists, but no compliance signal), enrolled without being compliant (Intune evaluates it and finds it failing), or every combination. The grant reads the object, so the object’s state — not the local client’s belief about itself — is ground truth for Conditional Access.

The three join types and what each can satisfy

trustType is the field that decides which device grant is even applicable to a machine. There is no compliant-vs-hybrid choice at the CA layer that overrides the physics of registration — a device that only ever workplace-joined cannot satisfy the hybrid grant, full stop.

Join type (trustType) Graph value How it’s created Typical device Can satisfy compliant? Can satisfy hybrid?
Entra registered (Workplace) Workplace User adds a work account to a personal device (BYOD) Personal Windows/macOS/mobile Only if also Intune-enrolled No
Entra hybrid joined ServerAd On-prem AD-joined + Entra Connect device sync + auto-registration Legacy corporate domain PC Only if also Intune-enrolled (co-managed) Yes
Entra joined AzureAd Cloud-native join (Autopilot / Out-of-box / bulk) Modern cloud-managed corporate PC Yes (typically Intune-enrolled) No

Two consequences fall straight out of this table. First, the hybrid grant is only ever satisfiable by hybrid-joined (ServerAd) devices — it is the compatibility bridge for legacy estates, not a general control. Second, an Entra registered (BYOD) device can satisfy the compliant grant, but only if the user also enrols it in Intune — which most BYOD users will refuse, which is exactly why BYOD belongs on the app-protection path, not the compliant path. For a cloud-native fleet, every device is AzureAd and Intune-enrolled, and the plain Require compliant grant is correct.

How isCompliant is produced and where it lives

isCompliant is written by exactly one system — Intune — and read by exactly one system for gating purposes — Conditional Access. It is a boolean on the Entra device object, and its provenance is the Intune compliance evaluation. Confirm it directly with Microsoft Graph rather than trusting any UI, because the whole point of the model is that the object is authoritative:

Connect-MgGraph -Scopes "Device.Read.All"

# The exact fields the compliant/hybrid grants evaluate
Get-MgDevice -Filter "displayName eq 'KV-LT-0421'" |
  Select-Object DisplayName, DeviceId, TrustType, IsCompliant, IsManaged, `
    OperatingSystem, OperatingSystemVersion, ApproximateLastSignInDateTime

TrustType is the join type (Workplace = Entra registered, AzureAd = Entra joined, ServerAd = hybrid joined); IsCompliant is the exact bit the compliant grant evaluates; IsManaged indicates Intune (or another MDM) manages it. If IsCompliant is empty/false but Intune’s device blade shows the device compliant, you are in one of two states: sync lag (the write hasn’t propagated yet) or a stale-aged bit (the validity window expired). The fields, what produces each, and what a wrong value means:

Device-object field Produced by Correct value for “managed corporate PC” What a wrong value means
trustType Registration / join process AzureAd (cloud) or ServerAd (hybrid) Workplace → BYOD; hybrid grant won’t apply
isCompliant Intune compliance evaluation true Blocked by compliant grant; check sync/ageing
isManaged The MDM taking management true (Intune) Not enrolled → isCompliant never set
operatingSystem Registration Windows / macOS / iOS / Android Filter platform mismatch
deviceOwnership Enrolment classification Company Personal → your corporate-only filter excludes it
approximateLastSignInDateTime Directory activity recent Stale → likely aged out of compliance

The end-to-end token-time decision

When a user opens Outlook on the web from a managed laptop, the sequence is: the browser (via WAM/the broker) attaches the device’s PRT to the token request → Entra reads the device object referenced by that PRT → Conditional Access evaluates every applicable policy against trustType / isCompliant (plus user, app, platform, filter) → the grant is satisfied or blocked → a token is (or isn’t) issued. The device state that CA evaluates is a snapshot from the object at that instant; nothing about the device’s live local state enters the decision except through the object. This is why “I just fixed BitLocker” doesn’t immediately unblock you — the fix has to reach the object (via an Intune check-in) before a new sign-in can read it.

Authoring the Intune compliance policy

A compliance policy is two things stapled together: a set of pass/fail rules (the device is compliant iff every rule passes) and an actions-for-noncompliance schedule (what happens, and when, once a rule fails). Build one per platform at Intune admin center → Devices → Compliance → Create policy, because the settings differ per OS and a single “all platforms” policy does not exist. The rule set is where you encode “healthy enough to be trusted”; the actions schedule is where you encode “humane enough not to flood the help desk.”

The settings classes (Windows baseline)

Windows compliance settings group into a handful of classes. Here is a sane production baseline with the choices and the gotchas — you do not need every setting, but you should decide on each class:

Settings class Example rules Sane baseline value Gotcha
Device Health Require BitLocker; Require Secure Boot; Require Code Integrity All on BitLocker rule needs the device to actually report the state; new devices lag
Device Properties Minimum / maximum OS version; valid OS builds A supported Windows build floor A too-high floor instantly marks not-yet-updated devices noncompliant
Configuration Manager Compliance (co-managed) Require device compliance from ConfigMgr On only if co-managed Only relevant with the ConfigMgr workload
System Security Require password/PIN; storage encryption; Firewall; TPM; Defender Antimalware + real-time protection; minimum antimalware version Password + encryption + firewall + Defender RTP Antimalware version rules churn as signatures update
Microsoft Defender for Endpoint Require the device at or under a machine risk score Medium Only evaluates once the MDE-Intune connector is enabled; otherwise silently ignored
Custom Compliance (scripted) A PowerShell discovery script + JSON rule As needed The script must return the exact keys the JSON expects

Two rules carry outsized blast radius. The minimum OS version rule is a fleet-wide time bomb if set aggressively: raise the floor to a build your whole estate hasn’t reached yet and you mark everything below it noncompliant the moment the policy applies — pin the floor to your lowest supported deployed build, not the latest. The Defender risk rule does nothing until the connector is enabled (next section); until then it is a no-op that gives false confidence.

Actions for noncompliance — the schedule that is your grace period

Every policy has an Actions for noncompliance tab, and this is what separates a humane rollout from a help-desk flood. Each action has a schedule (how many days after the device is found noncompliant the action fires). The critical insight: there is no separate “grace period” setting — the “Mark device noncompliant” schedule is the grace period, because it controls when isCompliant actually flips to false and CA starts blocking.

Action When (schedule) Purpose Rollout setting Steady-state setting
Mark device noncompliant 0 days (immediate) or after N days Controls when isCompliant flips false → this is the grace period 3 days 1 day (or 0 for high-security)
Send email to end user 0 / 1 / 3 days Warn before enforcement bites 0 and 2 days 0 and 1 day
Send push notification 0 / 1 days Same, on mobile 0 days 0 days
Add device to retire list Late (e.g. 30 days) Last-resort for abandoned devices Optional 30 days
Remotely lock the device Late Recover a lost/abandoned managed device Off during rollout Optional

Set Mark device noncompliant to 3 days during rollout: a freshly enrolled or briefly-failing device gets three days (and warning emails) before isCompliant flips and CA blocks it. Drop it to 1 day or 0 days (immediate) only once you are confident in the estate and want tighter enforcement. The email/push actions should fire before the mark-noncompliant action so users know why they’re about to be blocked. A subtle but important behaviour: the schedule is measured from when the device is found noncompliant, so a device that dips in and out of compliance can reset its clock — which is usually the humane outcome.

The two tenant-level traps

Two tenant-wide settings under Compliance → Compliance policy settings override everything and are the most common silent misconfigurations:

Tenant setting Default The trap Correct value (and when to set it)
Mark devices with no compliance policy assigned as Compliant Every unmanaged / unevaluated device is treated as compliant → your CA grant is silently toothless Not compliant — but only after real policies are assigned and grace periods are live
Compliance status validity period (days) 30 A device that stops checking in ages to noncompliant; too short → transient outages, too long → stale devices trusted 30 (tune to your check-in reliability)

The first setting is the classic “the grant does nothing” bug. Left at Compliant, a personal laptop with no Intune enrolment has no policy assigned, is therefore treated as compliant by default, and passes your Require compliant grant — the exact thing you built the grant to stop. You must set it to Not compliant — but flip it only after your real policies are assigned and grace periods are in place, or you will instantly mark every not-yet-evaluated device as failing and cause a self-inflicted outage. The second setting is the ageing mechanism: set it too short and reliable devices with brief check-in gaps get blocked; too long and a device that’s been offline (or compromised and quarantined from check-in) is still trusted.

Assign the policy to a device group or a user group (Intune supports both) — but start with a pilot ring (KV-Pilot-Windows), never All Devices. Assignment scoping is where filters (covered later) and ring deployment intersect; see Intune Filters: Assignment Targeting & Ring Deployment for the full targeting model.

Per-OS settings differences

The settings classes differ meaningfully per platform, and assuming a Windows setting exists elsewhere is a common trip-up. The high-value differences:

Setting area Windows macOS iOS/iPadOS Android Enterprise
Disk encryption BitLocker FileVault Data protection (enforced by passcode) Encryption of data storage
OS version floor Build number Version number Version number Version number / security patch level
Antimalware Defender Antimalware + RTP (limited; system integrity) N/A (sandboxed) Google Play Protect / SafetyNet-Play Integrity
Jailbreak / root detection N/A N/A Block jailbroken Block rooted / Play Integrity
Defender risk (MDE) Machine risk score Machine risk score Mobile risk (MDE for iOS) Mobile risk (MDE for Android)
Password / PIN Required, complexity Required, complexity Passcode, length Password, complexity
Firewall Required Required N/A N/A

The device-health integrity checks are the platform-specific heart of compliance: jailbreak/root detection on mobile (via the platform attestation — Apple’s device integrity, Google’s Play Integrity) is the mobile analogue of Secure Boot / Code Integrity on Windows. Build one policy per platform, assign each to its own pilot group, and expect the rules to differ even where the intent (“the device is healthy”) is identical.

The Defender for Endpoint risk signal

The static compliance rules above are a point-in-time check: is BitLocker on, is the OS current. The Microsoft Defender for Endpoint (MDE) integration adds a continuous signal — a machine risk score (Clear / Low / Medium / High) that MDE computes from active detections, and that Intune consumes as a compliance rule: Require the device to be at or under a machine risk score of X. A device that MDE scores above that threshold is marked noncompliant, and — through the chain you already understand — Conditional Access blocks it. This turns “the device was healthy this morning” into “the device is healthy right now, and not actively compromised,” which is the difference between a compliance checkbox and a real security control.

Wiring the connector

The risk rule is a no-op until the MDE ↔ Intune connector is enabled and device-compliance is switched on within it. The setup, in order:

Step Where What it does Common miss
1. Enable the connection Intune → Endpoint security → Microsoft Defender for Endpoint Establishes the Intune↔MDE trust
2. Turn on Connect Windows/macOS/iOS/Android devices to MDE Same blade, per platform Lets MDE onboard those devices Forgetting a platform → risk never scored there
3. Enable Allow MDE to enforce compliance / device-compliance toggle Same blade MDE actually feeds risk into compliance Left off → the risk rule silently never evaluates
4. Add the machine risk score rule to the compliance policy Compliance policy → Defender for Endpoint The rule that reads the risk Set to Clear accidentally → any detection blocks
5. Onboard devices to MDE Via Intune onboarding config / EDR policy Devices actually report risk Onboarding blob not deployed → no telemetry

Once wired, the flow is: MDE detects something and raises the machine risk → MDE pushes the risk to Intune → Intune re-evaluates the compliance policy → if risk exceeds the threshold, isCompliant flips false → the Entra object updates → CA blocks at next sign-in. Choosing the threshold is a security-vs-availability trade-off:

Risk-score threshold (“at or under”) What it blocks Availability impact When to use
Clear Any device with any detection High — a single low-severity alert blocks High-security enclaves only
Low Devices at Medium or High risk Moderate Sensitive workloads
Medium Devices at High risk only Low — only genuinely risky devices blocked Sensible default for most estates
High Only the worst (effectively “block only critical”) Minimal Very availability-sensitive; weak control

Medium (“block High-risk devices”) is the pragmatic default: it blocks devices MDE considers actively dangerous while tolerating the low-severity noise that would otherwise generate lockout tickets for benign detections. Note the ageing interaction: a device whose risk drops back to Clear does not instantly regain access — MDE must push the lowered risk, Intune must re-evaluate, and the object must update, so remediation-to-access has the same lag as any compliance change.

Building the require-compliant Conditional Access policy

With compliance producing isCompliant, the CA policy is where you consume it. Create it at Entra admin center → Protection → Conditional Access → New policy, and — this is non-negotiable — create it in Report-only first (see the staging section). The assignments and grant matter enormously; the two most dangerous mistakes both live here.

The grant choices

The device grant is one or two controls plus a “require one / require all” operator. Choosing the wrong combination is the number-one lockout cause:

Grant configuration Passes when… Right for Blast radius if wrong
Require device to be marked as compliant isCompliant = true (Intune) Cloud-native, all-Intune estates Blocks every non-enrolled device (incl. hybrid-only)
Require Microsoft Entra hybrid joined device trustType = ServerAd Legacy pure-hybrid estates Blocks every cloud-native / BYOD device
Both, Require one of the selected controls (OR) Either compliant OR hybrid Mixed estates mid-migration Safest for heterogeneous fleets
Both, Require all of the selected controls (AND) Compliant and hybrid Devices you want to be both Blocks cloud-native (not hybrid) and hybrid-not-enrolled

For a heterogeneous estate mid-migration, compliant OR hybrid-joined with Require one of the selected controls is the pragmatic grant: cloud-managed machines pass on compliance, legacy domain machines pass on hybrid join, nothing breaks while you migrate. Do not pick Require all across both unless you genuinely want devices to satisfy each simultaneously — that combination blocks a cloud-native (AzureAd) laptop because it is not hybrid, and blocks a hybrid PC that was never Intune-enrolled because it is not compliant. Almost everyone who selects “all” meant “one of.”

The assignments — where lockouts are born

The grant is only half the policy; the assignments decide who and what it applies to, and two assignment choices are where tenant-wide outages come from:

Assignment Safe day-one value Dangerous value Why
Users — include Pilot group (KV-Pilot-Windows) All users A bad grant on all users is a tenant outage
Users — exclude Break-glass accounts + service/automation identities (nothing excluded) Break-glass signs in from unmanaged devices; no exclusion = admin lockout
Target resources Office 365 All cloud apps “All apps” sweeps in the admin portals and registration endpoints you need to fix the policy
Conditions → Device platforms The platforms you’ve piloted (e.g. Windows) All / none Mis-scoping platforms blocks OSes you haven’t prepared
Conditions → Client apps As needed (default) Legacy-auth clients can’t present device state → hard-blocked

The two rules that prevent the worst outages: always exclude break-glass (a device-compliance grant is especially lethal to break-glass because the recovery account will almost never be on a compliant device — verify the exclusion on the new policy every single time), and scope to Office 365, not All cloud apps, on day one — because “All cloud apps” includes the Microsoft admin portals and the device-registration endpoints, so a misconfigured grant on “All apps” can lock you out of the very tools needed to undo it. See Entra Break-Glass Emergency Access, Monitoring & Governance for the full break-glass hygiene this depends on.

The policy as Graph

The equivalent shape via Graph (POST /identity/conditionalAccess/policies) — note it ships as report-only by design:

{
  "displayName": "CA-Require-Compliant-O365-Pilot",
  "state": "enabledForReportingButNotEnforced",
  "conditions": {
    "applications": { "includeApplications": ["Office365"] },
    "users": {
      "includeGroups": ["<pilot-group-id>"],
      "excludeUsers": ["<breakglass-1-id>", "<breakglass-2-id>"],
      "excludeGroups": ["<automation-identities-group-id>"]
    },
    "platforms": {
      "includePlatforms": ["windows"]
    }
  },
  "grantControls": {
    "operator": "OR",
    "builtInControls": ["compliantDevice", "domainJoinedDevice"]
  }
}

The API names are historical and worth memorising because they don’t match the portal labels: compliantDevice is the marked-compliant grant; domainJoinedDevice is the hybrid-joined grant (not “domain-joined” in the on-prem sense). operator: "OR" is Require one of the selected controls; "AND" is Require all. The state values map as follows — this is the field you flip to go live:

Graph state value Portal label Behaviour
enabledForReportingButNotEnforced Report-only Evaluates every sign-in, records the would-be result, enforces nothing
enabled On Fully enforcing
disabled Off Not evaluated at all

Create the policy via Graph PowerShell so it is repeatable and reviewable as code:

Connect-MgGraph -Scopes "Policy.ReadWrite.ConditionalAccess"

$params = @{
  displayName   = "CA-Require-Compliant-O365-Pilot"
  state         = "enabledForReportingButNotEnforced"   # report-only
  conditions    = @{
    applications = @{ includeApplications = @("Office365") }
    users        = @{
      includeGroups = @("<pilot-group-id>")
      excludeUsers  = @("<breakglass-1-id>", "<breakglass-2-id>")
    }
    platforms    = @{ includePlatforms = @("windows") }
  }
  grantControls = @{
    operator        = "OR"
    builtInControls = @("compliantDevice", "domainJoinedDevice")
  }
}
New-MgIdentityConditionalAccessPolicy -BodyParameter $params

Filters for devices: scoping by device attributes

A filter for devices matches (or excludes) on properties of the device object rather than the user — ownership, OS, model, join type, manufacturer, or one of 15 extension attributes. It is the scalpel that lets you say “compliance for corporate Windows only” or “exclude this kiosk fleet” without authoring a dozen policies. The filter lives in the CA policy’s assignments (Conditions → Filter for devices) and is a rule expression over device attributes, plus an include/exclude mode.

The rule syntax and attributes

The filter is configured with three fields — Configure (Yes/No), Mode (Include/Exclude), and Rule (the expression):

Filter for devices
  Configure : Yes
  Mode      : Include     (or Exclude)
  Rule      : device.trustType -eq "ServerAD" -and device.isCompliant -eq True

The usable device attributes (combine with -and / -or, group with parentheses) — this is the vocabulary of every filter you’ll write:

Attribute Example value Operators Use for
device.deviceOwnership "Company" / "Personal" -eq, -ne Corporate-only vs BYOD scoping
device.operatingSystem "Windows" / "macOS" -eq, -ne, -startsWith Per-OS policy without the platform condition
device.trustType "ServerAD" / "AzureAD" / "Workplace" -eq, -ne Hybrid-only / cloud-only scoping
device.isCompliant True / False -eq, -ne Compliance-aware filters
device.model "Surface Pro 9" -eq, -startsWith, -contains Model-based scoping
device.manufacturer "Microsoft Corporation" -eq, -contains Vendor-based scoping
device.extensionAttribute1..15 "kiosk" -eq, -ne, -startsWith, -contains Your own tagging system
device.deviceId a GUID -eq, -in Pinning specific devices
device.displayName "KV-KIOSK-07" -eq, -startsWith, -contains Name-pattern scoping
device.isRooted True / False -eq Excluding jailbroken/rooted

Common building blocks, ready to paste:

Need Rule
Corporate-owned only device.deviceOwnership -eq "Company"
Specific OS device.operatingSystem -eq "Windows"
Hybrid-joined only device.trustType -eq "ServerAD"
Cloud-joined only device.trustType -eq "AzureAD"
Tag a fleet for exclusion device.extensionAttribute1 -eq "kiosk"
Model-based device.model -startsWith "Surface"
Corporate Windows that’s compliant device.deviceOwnership -eq "Company" -and device.operatingSystem -eq "Windows" -and device.isCompliant -eq True

The include/exclude trap

This is the filter mistake that silently inverts your intent, so internalise it. The filter Mode interacts with the grant in a way that is not symmetric, and the interaction confuses even experienced admins:

Mode Meaning Combined with a block grant Combined with a require-compliant grant
Include Policy applies to devices matching the rule Blocks the matched devices Requires compliance only for matched devices
Exclude Policy applies to devices NOT matching the rule Blocks everything except matched Requires compliance for everything except matched (matched devices are exempt)

The trap: Include and Exclude are about which devices the policy applies to, not “allow” vs “deny.” An Exclude filter of device.extensionAttribute1 -eq "kiosk" on a require-compliant policy means “apply this compliance requirement to every device except kiosks” — i.e. kiosks are exempt from needing compliance. That is usually what you want (carve kiosks out without weakening the grant for anyone else). But people routinely write Include ... -eq "kiosk" thinking it excludes kiosks, and instead they’ve made the policy apply only to kiosks — leaving every other device ungated. Always read the mode as “the policy applies to devices where the rule is [true for Include / false for Exclude],” and validate with What If before enforcing.

Extension attributes — powerful and over-claimed

The 15 device extension attributes (extensionAttribute115) are the most powerful and most misunderstood part of filters. They are a tagging system you own on the device object, and they are written via Microsoft Graph on the device objectnot the AD user’s msDS-cloudExtensionAttribute fields, not the on-prem AD computer object, not the Intune device record. This confusion sends people editing the wrong object for hours. Set one via Graph so a filter can key off it:

Connect-MgGraph -Scopes "Device.ReadWrite.All"

$deviceObjectId = (Get-MgDevice -Filter "displayName eq 'KV-KIOSK-07'").Id
Update-MgDevice -DeviceId $deviceObjectId -BodyParameter @{
  extensionAttributes = @{ extensionAttribute1 = "kiosk" }
}

# Verify the tag landed on the right object
Get-MgDevice -DeviceId $deviceObjectId |
  Select-Object DisplayName, @{n='ext1';e={ $_.ExtensionAttributes.ExtensionAttribute1 }}

Where extension attributes come from and don’t, so you tag the right thing:

Attribute source Is it the CA filter attribute? Written via Notes
Entra device extensionAttributes Yes Graph on the device object The one filters use
Entra user onPremisesExtensionAttributes No Sync from on-prem AD user User object, not device
On-prem AD computer attributes No AD tooling Not synced into the CA filter attribute
Intune device category / notes No Intune Different store; not a CA filter attribute

Two practical patterns close the section. An Exclude filter of device.extensionAttribute1 -eq "kiosk" carves shared/kiosk devices out of the require-compliant policy without weakening it for anyone else. An Include filter of device.deviceOwnership -eq "Company" keeps the grant on corporate hardware only, leaving BYOD to the app-protection path. Treat the 15 attributes as documented, owned tags — write down which attribute means what, because nothing in the platform tells you extensionAttribute3 is your “PCI-scope” flag.

Device-based vs app-based: managed desktops and personal mobiles

The require-compliant grant is right for managed endpoints and wrong for personal phones. Demanding Intune compliance on a BYOD phone forces full enrolment — which gives your organisation management authority over a personal device and which users will (rightly) refuse, driving them to shadow-IT workarounds. The clean architecture is two parallel policies: the compliant grant governs desktops (device-based), and a separate app-protection grant governs mobiles (app-based, no enrolment required).

The two-policy split

Dimension Desktop policy (device-based) Mobile policy (app-based)
Platforms Windows, macOS iOS, Android
Client apps condition (default) Mobile apps and desktop clients
Grant Require compliant or hybrid-joined Require app protection policy (Intune MAM)
Enrolment required? Yes (compliant needs Intune) No — MAM protects the app, not the device
Protects The whole device Corporate data inside approved apps
User friction Managed corporate hardware Zero enrolment; user keeps a personal device

The app-protection policy (Intune MAM) approach protects corporate data within managed apps (Outlook, Teams, the mobile Office apps) — enforcing PIN, encryption, copy-paste restrictions, and selective wipe of corporate data — without the organisation managing the whole device. It is the correct control for BYOD mobiles, and it is a full topic in its own right; see Intune MAM: App Protection Without Enrolment (BYOD) for authoring the App Protection Policies the Require app protection policy grant depends on. Without an assigned APP, the grant has nothing to require and blocks the sign-in.

The retired approved-client-app grant

A critical 2026 fact that breaks old designs: the legacy Require approved client app grant has been retired — it stopped functioning in early March 2026. Any policy still authored against it no longer enforces. New (and migrated) mobile policies must use Require app protection policy instead. The migration and the distinction:

Grant Status (2026) What it required Replacement
Require approved client app Retired (stopped working early March 2026) The app is on Microsoft’s approved-client list Require app protection policy
Require app protection policy Current The app has an Intune App Protection Policy applied (this is the replacement)

If you inherit a tenant with mobile CA policies, audit for the retired grant first — a policy that looks like it’s protecting mobile may be silently doing nothing. Convert each to Require app protection policy and confirm the App Protection Policies are assigned to the mobile user population.

Session control as a third option

For unmanaged-but-low-risk web access, Conditional Access App Control (session control via Defender for Cloud Apps) is a third grant — a monitored or restricted browser session rather than an outright block. It lets an unmanaged device reach a web app but strips or watches risky actions (block download, block copy, monitor only), which is the right answer when “block entirely” is too blunt for a given app and audience. See Defender for Cloud Apps: Shadow IT & Session Policies for the session-control mechanics. The three grant families, side by side:

Grant family Device requirement User experience Best for
Device-based (Require compliant / hybrid) Managed + compliant device Transparent on managed devices Corporate desktops/laptops
App-based (Require app protection policy) App is MAM-protected (no device enrolment) Slight friction inside managed apps BYOD mobiles
Session-based (Use CA App Control) None (unmanaged allowed) Restricted/monitored browser session Unmanaged web access to specific apps

Per-OS specifics: how each platform presents device state

The “device not compliant” error is disproportionately an OS-side problem — the compliance is real in Intune and on the object, but the client failed to present the device state in the token request. Each platform has a different broker and a different failure mode, and knowing your platform’s mechanism is half the diagnosis.

Windows — PRT and WAM

On Windows, the Primary Refresh Token (PRT) is the artefact that proves device identity and state to Entra; it is issued when the device registers/joins and is presented by the Web Account Manager (WAM) broker during token requests. Browsers must use WAM (Edge natively; Chrome via the Windows Accounts extension; Firefox via configuration) or they present no device state and CA sees an unknown device → not compliant. Confirm the PRT on the device:

:: Run as the signed-in user (not elevated) — shows the device SSO state
dsregcmd /status

:: Key lines to read:
::   AzureAdJoined : YES        (or DomainJoined : YES for hybrid)
::   AzureAdPrt    : YES        <- the PRT must be present
::   AzureAdPrtAuthority / AzureAdPrtUpdateTime

AzureAdPrt : YES is the field that matters: if it is NO, the device cannot present its state and CA will block it regardless of Intune compliance. Common Windows presentation failures and fixes:

Symptom Cause Confirm Fix
Compliant device blocked in Chrome, works in Edge Chrome not using WAM dsregcmd /status shows PRT=YES Install Windows Accounts extension / enable browser SSO
PRT absent (AzureAdPrt : NO) Registration incomplete, expired, or clock skew dsregcmd /status Re-trigger registration; fix time sync; re-sign-in
Hybrid device not seen as hybrid Device sync not completed via Entra Connect Device object missing / trustType wrong Confirm Connect device sync; wait for object
Works, then blocks after a while PRT expired and didn’t renew AzureAdPrtUpdateTime old Ensure network to Entra; re-authenticate

macOS — the Enterprise SSO plug-in

On macOS, device state is presented via the Microsoft Enterprise SSO plug-in (delivered through an Intune configuration profile) plus the device’s registration. Without the SSO plug-in profile, Safari/Chrome sign-ins don’t carry device state and compliant Macs get blocked. The Mac-specific chain: enrol in Intune → deploy the Enterprise SSO extension profile → the device registers → the plug-in presents state on token requests. See Intune macOS Management: Platform SSO, FileVault & DDM for deploying the SSO extension correctly.

iOS / Android — the broker apps

On mobile, the broker is Microsoft Authenticator (iOS) or the Company Portal / Authenticator (Android); apps and the system browser present device state through it. On these platforms the compliant grant requires enrolment (so it’s a corporate-mobile control), while BYOD mobiles use the app-protection grant instead. The per-OS presentation mechanism, summarised:

OS Device-state broker Delivered by “Not presented” failure looks like
Windows WAM + PRT Join/registration Blocked in non-WAM browser; PRT=NO
macOS Enterprise SSO plug-in Intune config profile Blocked until SSO extension deployed
iOS/iPadOS Microsoft Authenticator broker Authenticator app Blocked if app not brokering / not enrolled (for compliant grant)
Android Company Portal / Authenticator Company Portal app Blocked if Company Portal absent (for compliant grant)

Staging the rollout: report-only, What If, sign-in logs

Never flip a device grant straight to On. The device-compliance grant has the largest surprise blast radius of any CA control because its correctness depends on three asynchronous systems, so the staging discipline is not optional. The safe sequence has three instruments.

Report-only

Set the policy state to Report-only (enabledForReportingButNotEnforced): it evaluates every sign-in and records what it would have done, enforcing nothing. Leave it for at least a full business cycle — a week — so daily, weekly, and edge-case sign-ins all get sampled. Report-only is the single most important safety net; it turns “we hope this works” into “we have data on exactly who breaks.”

What If

Use Conditional Access → What If to simulate a specific user + app + device-state + platform combination and see which policies apply. Run it for every persona before enforcing:

Persona to simulate Expected result If it’s wrong
Compliant pilot user, Windows, Office 365 Grant satisfied (passes) Check the object’s isCompliant; check filter
Noncompliant device (BitLocker off) Blocked If it passes → “no policy = compliant” trap
Break-glass account, unmanaged device Not applied If applied → fix the exclusion immediately
Hybrid-only legacy PC (not Intune) Passes via the hybrid control If blocked → you’re using compliant-only, not OR
Kiosk device (tagged) Not applied (excluded by filter) If applied → filter mode is inverted
BYOD mobile Governed by the mobile policy, not this one If this one applies → platform scope wrong

What If evaluates the policy logic against stated inputs; it does not verify the device’s actual current state, so pair it with real sign-ins from real devices.

Sign-in log analysis

This is where you find surprises before users do. In Entra → Monitoring → Sign-in logs, the Report-only tab shows, per sign-in, whether each report-only policy would grant, block, or require. The results you care about:

Report-only result Meaning Action
reportOnlySuccess Would have passed Fine
reportOnlyFailure Would have blocked this sign-in Your list of who breaks — remediate before enforcing
reportOnlyInterrupted Would have required interactive action (e.g. re-auth) Investigate; usually acceptable
reportOnlyNotApplied Policy didn’t apply (scope/exclusion) Confirm this is intended (e.g. break-glass)

If sign-ins are exported to Log Analytics, query them directly to quantify the impact and get the exact user/device list:

SigninLogs
| where TimeGenerated > ago(7d)
| mv-expand policy = todynamic(ConditionalAccessPolicies)
| where policy.displayName == "CA-Require-Compliant-O365-Pilot"
| extend reportOnlyResult = tostring(policy.result)
| where reportOnlyResult in ("reportOnlyFailure", "reportOnlyInterrupted")
| summarize impacted = dcount(UserPrincipalName),
            sample   = make_set(UserPrincipalName, 20)
    by reportOnlyResult, tostring(DeviceDetail.operatingSystem),
       tostring(DeviceDetail.isCompliant)
| order by impacted desc

reportOnlyFailure is your enforcement risk: the list of users/devices that break the moment you switch the policy on. Drive it to effectively zero — enrol/remediate the devices, fix the scope, or add a filter exclusion — then set state to enabled. Expand the ring (pilot → department → all) one step at a time, re-checking the report-only data at each step. The rollout as a staged sequence:

Stage state Scope Gate to advance
1. Report-only enabledForReportingButNotEnforced Pilot group A week of data collected
2. What If sweep (unchanged) All personas Every persona resolves correctly
3. Drive failures to zero (unchanged) Pilot reportOnlyFailure ≈ 0
4. Enforce pilot enabled Pilot group only Pilot stable for a few days
5. Expand rings enabled Dept → all Re-check report-only at each ring

Architecture at a glance

Picture the system as a left-to-right pipeline across three planes, because that layout mirrors exactly how a sign-in flows and where each failure bites. On the far left sits the device plane: a managed endpoint (Windows/macOS/iOS/Android) that has (a) an Entra device object with a trustType, and (b) an Intune enrolment. Intune runs the compliance policy against the device on each check-in — evaluating device health (BitLocker/Secure Boot), OS-version floor, system security, and the Defender for Endpoint machine-risk signal fed in from the MDE connector — and stamps the result as isCompliant back onto the Entra device object. That write is the arrow crossing from the device plane into the directory.

The centre is the directory plane — the Entra device object holding the two fields that decide everything: trustType (registered / hybrid / joined) and isCompliant. This object is the single source of truth; nothing about the device’s live local state reaches the decision except through it, and the Compliance status validity period governs how long a value stays trusted before ageing to false. When the user opens Office 365, the client’s broker (WAM+PRT on Windows, the Enterprise SSO plug-in on macOS, Authenticator/Company Portal on mobile) attaches the device identity to the token request — the arrow from the device plane into the right-hand plane.

The right is the policy planeConditional Access reading the device object at token time. Two grant paths run in parallel: the device-based path (Require compliant OR hybrid-joined, scoped by a filter for devices to corporate hardware, excluding kiosks by extension attribute) governs desktops, while the app-based path (Require app protection policy) governs BYOD mobiles. A break-glass exclusion sits across both paths as a bypass lane so recovery accounts are never gated. The decision — allow / block / require — is emitted here, and in Report-only mode it’s recorded (as reportOnlySuccess / reportOnlyFailure) rather than enforced. Read the whole picture as: Intune produces the signal → the directory object holds it → the client presents it → Conditional Access decides on it. Every “device not compliant” ticket is a break somewhere along that single left-to-right arrow, and the diagnostic is to walk it from whichever end you can observe.

Real-world scenario

Nordwind Manufacturing, a 9,000-seat industrial firm, ran identity-only Conditional Access (MFA + sign-in risk) and, pushed by a cyber-insurance renewal, moved to require a compliant device for Office 365. Their estate was mixed: about 5,500 Autopilot-provisioned AzureAd Windows laptops (Intune-managed), 2,800 legacy ServerAd hybrid-joined desktops on the factory floor (domain-joined, not Intune-enrolled), and a long tail of BYOD phones. The endpoint team was six engineers; they staged carefully — a full report-only week on a 300-device pilot, What If runs for each persona, reportOnlyFailure driven to zero — and flipped Require compliant OR hybrid-joined to On for Office 365 on a Tuesday.

Within the hour the help desk lit up: Outlook and Teams failures from Autopilot laptops that were demonstrably Compliant in Intune. The report-only week hadn’t predicted it, which is what made it alarming. The breakthrough came from asking the right first question — does the Entra object agree with the Intune blade? — and running one Graph query against the affected ring:

Connect-MgGraph -Scopes "Device.Read.All"
# Windows devices that signed in recently but the OBJECT says non-compliant
Get-MgDevice -All -Filter "operatingSystem eq 'Windows'" |
  Where-Object {
    -not $_.IsCompliant -and
    $_.ApproximateLastSignInDateTime -gt (Get-Date).AddDays(-2)
  } |
  Select-Object DisplayName, IsCompliant, TrustType, `
    ApproximateLastSignInDateTime, RegistrationDateTime |
  Measure-Object

It returned ~340 devices: Compliant in Intune’s blade, but IsCompliant = false on the Entra object. Root cause: their Compliance status validity period was 30 days, and a large Autopilot batch had a check-in gap — a proxy change on the corporate VLAN had bypassed and then blocked the Intune check-in endpoints (*.manage.microsoft.com, *.dm.microsoft.com) for that subnet. Those devices had stopped reporting to Intune weeks earlier; the 30-day validity window expired; isCompliant aged to false on the object even though each device’s local Intune client still showed green from its last successful evaluation. CA read the stale-aged object and blocked. Report-only had sampled sign-ins, not the silent ageing of the compliance bit — so it saw nothing wrong right up until the bit expired.

The fix was two-pronged and fast. Immediately: re-scope the CA policy with a transient grace filter — an Exclude filter on device.extensionAttribute2 -eq "checkin-remediation", with that tag written via Graph onto the affected device IDs — so those ~340 machines fell out of enforcement while they recovered, without weakening the grant for the other 8,660 devices. In parallel: unblock *.manage.microsoft.com and *.dm.microsoft.com on the proxy so check-ins resumed. As each device checked in and re-evaluated to compliant, its bit refreshed on the object; the team then removed the extensionAttribute2 tag, folding it back into enforcement. Full recovery took about six hours, with zero data-loss and no revenue impact, versus the day-long outage a “turn the policy off” reflex would have caused. The lesson on the wall: “Report-only samples sign-ins, not the ageing of the compliance bit. Before you enforce, confirm devices are actively checking in — not just nominally compliant.” They added a standing alert on devices whose ApproximateLastSignInDateTime was recent but IsCompliant was false, catching the divergence early ever after.

Advantages and disadvantages

The three-system device-compliance model is the highest-signal CA control there is — and its power and its fragility come from the same source: it depends on Intune, Entra, and CA all agreeing about a device, asynchronously. Weigh it honestly:

Advantages (why the model is worth it) Disadvantages (why it bites)
Moves trust from “password + phone” to “a continuously-evaluated managed device” — the core Zero Trust win Depends on three asynchronous systems agreeing; eventual, not immediate, consistency
Stops token theft / AiTM: a stolen cookie replayed from an unmanaged device fails the device grant The compliance bit ages; a check-in gap silently blocks nominally-compliant devices
The compliant OR hybrid grant bridges mixed estates so migration doesn’t require a big-bang cutover Require compliant on a non-enrolled fleet blocks all of it; easy to pick the wrong grant
Filters for devices scope precisely (corporate-only, exclude kiosks) without policy sprawl The include/exclude mode silently inverts intent; a mis-set filter ungates everyone
The MDE risk signal makes compliance continuous, not point-in-time The risk rule is a silent no-op until the connector is fully wired
Report-only + What If + sign-in logs give a real dry run before enforcement Defaults are unsafe: “no policy = compliant” disarms the grant; “mark noncompliant = 0 days” whiplashes rollout
The Entra device object is a single, queryable source of truth (Graph) “Not compliant” often means the client didn’t present state (missing PRT/broker), not that the device is actually noncompliant

The model is right for any organisation serious about Zero Trust device posture — which cyber-insurance and regulation increasingly mandate. It bites hardest on mixed estates (pick the OR grant), on teams that treat it as a checkbox (the defaults will disarm or lock out), and on BYOD-heavy shops that try to force enrolment instead of using the app-protection path. Every disadvantage is manageable — but only if you know it exists and staged for it, which is the entire point of the discipline in this article.

Hands-on lab

Build the full stack in a test tenant (or a scoped pilot), confirm compliance flows to the object, and verify a compliant device passes while a noncompliant one is blocked — all staged through report-only so nothing enforces until you say so. Use a test user and 1–2 test devices; a Microsoft 365 E3/E5 or EMS trial tenant with Intune is sufficient.

Step 1 — Create pilot groups and a break-glass exclusion group.

Connect-MgGraph -Scopes "Group.ReadWrite.All", "Device.Read.All"

# Pilot group for the compliance policy + CA policy
New-MgGroup -DisplayName "KV-Pilot-Windows" -MailEnabled:$false `
  -SecurityEnabled:$true -MailNickname "KV-Pilot-Windows"

# Confirm your break-glass accounts exist and note their object IDs
Get-MgUser -Filter "startswith(userPrincipalName,'breakglass')" |
  Select-Object DisplayName, Id, UserPrincipalName

Expected: a new security group, and your two break-glass account IDs. If you don’t have break-glass accounts yet, stop and create them first — do not proceed with a device grant without them.

Step 2 — Author a Windows compliance policy (portal). At Intune → Devices → Compliance → Create policy → Windows 10 and later:

Expected: the policy shows as assigned; give it time to evaluate on the next device check-in.

Step 3 — Set the tenant defaults safely. At Intune → Devices → Compliance → Compliance policy settings: confirm Compliance status validity period = 30 days. Leave Mark devices with no compliance policy assigned as at Compliant for now — you flip it to Not compliant only after real policies cover your production estate. (In this lab, leave it as-is so you don’t block yourself.)

Step 4 — Confirm compliance reached the Entra object. After a test device checks in and evaluates, verify the object — the whole point of the model is that the object is authoritative:

Get-MgDevice -Filter "displayName eq 'KV-LT-TEST01'" |
  Select-Object DisplayName, TrustType, IsCompliant, IsManaged, OperatingSystem

Expected: IsCompliant : True, TrustType : AzureAd (or ServerAd for a hybrid test device). If IsCompliant is empty, wait for the next check-in (sync lag) — do not proceed until the object agrees with Intune.

Step 5 — Create the CA policy in report-only.

Connect-MgGraph -Scopes "Policy.ReadWrite.ConditionalAccess"

$pilot = (Get-MgGroup -Filter "displayName eq 'KV-Pilot-Windows'").Id
$bg1   = "<breakglass-1-id>"; $bg2 = "<breakglass-2-id>"

$params = @{
  displayName   = "CA-Require-Compliant-O365-Pilot"
  state         = "enabledForReportingButNotEnforced"   # REPORT-ONLY
  conditions    = @{
    applications = @{ includeApplications = @("Office365") }
    users        = @{ includeGroups = @($pilot); excludeUsers = @($bg1, $bg2) }
    platforms    = @{ includePlatforms = @("windows") }
  }
  grantControls = @{ operator = "OR"
                     builtInControls = @("compliantDevice", "domainJoinedDevice") }
}
New-MgIdentityConditionalAccessPolicy -BodyParameter $params

Expected: the policy is created in report-only, scoped to Office 365, pilot users only, break-glass excluded, compliant-OR-hybrid grant.

Step 6 — Run What If for every persona. In Entra → Conditional Access → What If, simulate: (a) a pilot user on a compliant Windows device → policy applies, grant satisfied; (b) a break-glass account on any device → Not applied; © a noncompliant device → applies, would block. Confirm each matches the expected-result table above.

Step 7 — Analyse the report-only signal. After a day, in Entra → Sign-in logs → Report-only tab (or the KQL query above), find any reportOnlyFailure. Expected in a healthy pilot: near-zero. Any failure is a device to enrol/remediate before you’d enforce.

Validation checklist. You built a compliance policy with a real grace period, confirmed isCompliant reached the Entra object via Graph, created a report-only CA policy with the correct compliant-OR-hybrid grant and a verified break-glass exclusion, validated every persona in What If, and read the report-only signal — all without enforcing a thing. To go live you would only flip state to enabled after reportOnlyFailure is zero. The lab steps mapped to what each proves:

Step What you did What it proves
2 Compliance policy with Mark noncompliant = 3 days The grace period is the actions schedule
3 Left “no policy = Compliant” untouched The tenant default is a deliberate, dangerous switch
4 Graph-confirmed IsCompliant on the object The object, not the blade, is what CA reads
5 Report-only CA policy, break-glass excluded Safe staging + the lockout-prevention exclusion
6 What If per persona The policy logic is correct before enforcement
7 Read reportOnlyFailure You know exactly who breaks before they do

Cleanup. Delete the CA policy (Remove-MgIdentityConditionalAccessPolicy -ConditionalAccessPolicyId <id>), the compliance policy, and the pilot group. Because you never enforced (report-only throughout) and never flipped the tenant default, there is nothing to un-break — which is the whole point of staging.

Common mistakes & troubleshooting

This is the playbook — the part you bookmark for the ticket that says “my device is Compliant in Intune but Conditional Access won’t let me in.” First as a scannable table you read mid-incident, then the reasoning for the entries that bite hardest.

# Symptom Root cause Confirm (exact cmd / portal path) Fix
1 Device Compliant in Intune blade, but CA blocks it isCompliant not yet written (sync lag) Get-MgDevice ... | Select IsCompliant = empty/false; Intune shows green Wait for next Intune check-in; then re-sign-in (new session)
2 Was working, now blocked; device went quiet in Intune Compliance validity aged the bit to false Object IsCompliant=false but ApproximateLastSignInDateTime recent; check-in gap Restore check-in (network/proxy to *.manage.microsoft.com); grace-filter the ring meanwhile
3 Blocked in Chrome/Firefox, works in Edge Browser not using WAM → no device state presented dsregcmd /status shows AzureAdPrt : YES Install Windows Accounts extension / enable browser SSO
4 Blocked; dsregcmd shows AzureAdPrt : NO PRT missing/expired → device state never presented dsregcmd /status Re-trigger registration; fix time sync; re-authenticate
5 Every hybrid-joined domain PC is blocked Grant is Require compliant on a non-enrolled fleet Sign-in log: failure reason “compliant”; devices not in Intune Change grant to compliant OR hybrid-joined (OR operator)
6 Unmanaged devices sail through the grant “No policy assigned = Compliant” tenant default Compliance policy settings shows Compliant Set to Not compliant (after real policies are live)
7 Kiosk/shared devices unexpectedly blocked (or unexpectedly ungated) Filter include/exclude inverted What If on a tagged device; read filter Mode Flip Include↔Exclude to match intent; re-run What If
8 Admins locked out of the portal after enforcing Grant on All cloud apps, no break-glass exclusion Policy scope = All apps; break-glass not excluded Use break-glass to scope to Office 365 + exclude break-glass
9 Every briefly-remediating device blocks during rollout Mark noncompliant at 0 days (no grace) Compliance policy → Actions = 0 days Set to 3 days during rollout; tighten later
10 macOS Compliant but blocked in browser Enterprise SSO plug-in not deployed No SSO extension profile assigned; Mac registered Deploy the macOS Enterprise SSO extension via Intune
11 Legacy Outlook/ActiveSync client hard-blocked Legacy-auth client can’t present device state Sign-in log: client app = “Other clients”/legacy Move to modern-auth client; block legacy auth separately
12 High-risk device suddenly blocked MDE risk rule flipped it noncompliant Compliance shows Defender-risk rule failing; MDE alert Remediate the MDE detection; risk drops → re-evaluates
13 Defender-risk rule “does nothing” MDE connector / device-compliance toggle off MDE connector blade shows disabled Enable connector + “allow MDE to enforce compliance” per platform
14 Compliant device sometimes blocked, inconsistently Existing token carried old (blocked) state Passes on fresh sign-in, fails on cached session Sign out fully / use a fresh session; token refresh picks up new state
15 Automation/service sign-in blocked by the grant Non-interactive identity has no device Sign-in log: service principal / no device Exclude the automation identity from the device-grant policy

The expanded reasoning for the entries that cause the most wasted hours:

1. Compliant in Intune, blocked by CA — sync lag. The Intune blade and the Entra object are different stores updated on different schedules. Intune shows the result of the last evaluation; the object shows what was written to Entra, which lags by a check-in. Confirm: Get-MgDevice ... | Select IsCompliant returns empty/false while Intune shows green. Fix: wait for the next check-in, then start a fresh sign-in — an existing token won’t reflect the new state.

2. Was working, now blocked — the aged compliance bit. The subtlest and highest-impact failure (the Nordwind scenario). A device that stops checking in has its isCompliant reverted to false after the Compliance status validity period, even though its local Intune client still shows compliant. Confirm: the object shows IsCompliant = false while ApproximateLastSignInDateTime is recent — the tell-tale divergence — and Intune’s last check-in for the device is old. Fix: restore check-in connectivity (usually a proxy/firewall blocking *.manage.microsoft.com / *.dm.microsoft.com); as an emergency, add an Exclude filter tagging the affected devices so they fall out of enforcement until they re-evaluate.

4. AzureAdPrt : NO — the PRT is missing. CA can only evaluate device state that the client presents, and on Windows that presentation is the PRT. No PRT, no device state in the token request, and CA sees an unknown device → not compliant — on a device that is genuinely compliant. Confirm: dsregcmd /status shows AzureAdPrt : NO. Fix: re-trigger device registration, correct clock skew (PRT is time-sensitive), and re-authenticate; the PRT re-issues.

5. Every hybrid domain PC blocked — wrong grant. The single most common design error: Require compliant on a fleet of hybrid-joined machines that were never Intune-enrolled. None of them has ever had isCompliant set, so all are blocked. Confirm: the sign-in log failure reason cites the compliant control, and the devices are absent from Intune. Fix: change the grant to compliant OR hybrid-joined with the OR operator, so hybrid PCs pass on join type while cloud-managed ones pass on compliance.

6. Unmanaged devices sail through — the toothless grant. The grant is on, but “no policy assigned = Compliant” means unmanaged/unevaluated devices are treated as compliant and pass. Confirm: Compliance policy settings shows Compliant for the default. Fix: set it to Not compliant — but only after your real policies cover the production estate, or you’ll instantly block every not-yet-evaluated device.

7. Kiosks blocked or ungated — filter inversion. The include/exclude mode is about which devices the policy applies to, not allow/deny. Confirm: run What If on a tagged device and read the Mode. Fix: to exempt kiosks from the compliance requirement, use Exclude device.extensionAttribute1 -eq "kiosk"; Include with the same rule would apply the policy only to kiosks and ungate everyone else.

14. Inconsistent blocking — the token snapshot. CA evaluates the device state at token time, and an existing token carries whatever decision it was issued under. So a device can pass on a fresh sign-in and “fail” on a cached session that predates the compliance flip. Confirm: it works in a fresh/incognito session but fails in the existing one. Fix: sign out fully; the new session’s token request re-reads the current object state.

Best practices

Security notes

Cost & sizing

The device-compliance stack is licensing-gated, not compute-gated — there’s no per-transaction cost, but the required licences are the real spend, and they’re per-user.

There is essentially no marginal runtime cost: compliance evaluation, the CA decision, and the Graph writes are platform functions, not billed operations. The sizing question is licence coverage, not capacity. A rough per-user monthly picture (indicative INR list-price bands; negotiate via EA/CSP):

Component Licence that includes it Rough INR / user / month (indicative) Notes
Conditional Access (P1) Entra ID P1 / M365 E3 / EMS E3 ~₹500–700 (P1 standalone) Baseline for the compliant grant
Risk-based conditions (P2) Entra ID P2 / M365 E5 / EMS E5 ~₹800–1,000 (P2 standalone) Only if you use user-risk too
Intune (compliance + MAM) Intune P1 / M365 E3 / EMS E3 ~₹700–900 (Intune P1 standalone) Required — no Intune, no compliance
Defender for Endpoint (risk) MDE P1/P2 / M365 E5 Security ~₹300–1,000 depending on plan Only for the machine-risk rule
App Protection Policies (included with Intune) ₹0 incremental The BYOD mobile grant

The pragmatic packaging: Microsoft 365 E3 covers CA (P1) + Intune for the whole desktop-compliance + MAM design; add E5 (or E5 Security) for the MDE risk signal and P2 risk conditions. Most organisations already hold E3 for other reasons, so the incremental cost of building this stack is often zero — the spend is the licence you already own, and the “cost” is the engineering discipline to stage it safely.

Interview & exam questions

1. What is the difference between the Require compliant and Require hybrid-joined CA grants, and when do you use each? Require compliant needs the device to be Intune-enrolled and evaluated (isCompliant = true); Require hybrid-joined only needs the device to be hybrid Entra-joined (trustType = ServerAd) and does not need Intune. Use compliant for cloud-native / Intune-managed estates, hybrid for legacy pure-domain estates, and compliant OR hybrid-joined (OR operator) for mixed estates mid-migration.

2. A device is Compliant in the Intune blade but Conditional Access blocks it. Name three distinct causes and how you’d confirm each. (a) Sync lagisCompliant not yet written to the Entra object; confirm with Get-MgDevice ... | Select IsCompliant (empty/false while Intune shows green). (b) Aged compliance bit — the device stopped checking in and the validity period expired; confirm via the object showing IsCompliant=false with a recent last sign-in but an old Intune check-in. © Missing PRT / broker — the client didn’t present device state; confirm with dsregcmd /status (AzureAdPrt : NO) on Windows.

3. What does “Mark devices with no compliance policy assigned as: Compliant” do, and why is it dangerous? It’s a tenant default: any device with no assigned compliance policy is treated as compliant, so unmanaged/unevaluated devices pass the Require compliant grant — silently making it toothless. Set it to Not compliant, but only after real policies cover the estate, or you’ll instantly block every not-yet-evaluated device.

4. Where does the grace period for compliance live? In the Actions for noncompliance schedule — specifically the Mark device noncompliant action’s delay (e.g. 3 days). There is no separate “grace period” setting; that delay controls when isCompliant actually flips to false and CA starts blocking.

5. Explain the include/exclude trap in filters for devices. The filter Mode controls which devices the policy applies to, not allow/deny. Include rule applies the policy only to devices matching the rule; Exclude rule applies it to devices not matching. To exempt kiosks from a compliance requirement you use Exclude on their tag; Include on the same tag would apply the policy only to kiosks and leave everything else ungated.

6. How does the Defender for Endpoint risk signal integrate with device compliance, and what must be enabled? MDE computes a machine risk score; Intune consumes it as a compliance rule (at or under a risk level). The MDE↔Intune connector must be enabled, the platform connected, and device-compliance enforcement toggled on within it — otherwise the risk rule is a silent no-op. A risk above the threshold flips isCompliant false and CA blocks at next sign-in.

7. Why is the compliant-device grant especially dangerous to break-glass accounts? Break-glass (recovery) accounts almost never sign in from an enrolled, compliant device, so if they aren’t excluded, a device-compliance grant is the first thing that blocks your recovery account — locking you out of the portal needed to undo the policy. Exclude break-glass from every CA policy and verify it every time.

8. Why do personal phones belong on the app-protection path rather than the compliant grant? Require compliant needs Intune enrolment, which gives the org management authority over the whole personal device — users refuse it. Require app protection policy (Intune MAM) protects corporate data inside managed apps (PIN, encryption, selective wipe) without enrolling the device, so it’s the correct BYOD-mobile control.

9. A user gets in from Edge but is blocked from the same device in Chrome. What’s happening? Chrome isn’t using the WAM broker, so it doesn’t attach the device’s PRT to the token request — CA sees an unknown device and blocks, even though the device is compliant. Fix by installing the Windows Accounts extension (or enabling browser SSO) so Chrome presents device state; dsregcmd /status confirms the PRT is present.

10. What replaced the Require approved client app grant, and why does it matter? It was retired (stopped functioning in early March 2026) and is replaced by Require app protection policy. It matters because a legacy mobile policy still authored against the retired grant no longer enforces — so a tenant can look protected while doing nothing; audit and convert those policies.

11. Describe the compliance→CA token flow and where a stale token bites. Device checks in → Intune evaluates → writes isCompliant to the Entra object → CA reads the object at the next sign-in/token request. CA evaluates a snapshot at token time, so an existing token carries the old decision until the session refreshes — which is why a just-remediated device can still be blocked on a cached session but passes on a fresh sign-in.

12. How do you stage a device-compliance policy safely, and why isn’t report-only alone sufficient? Report-only (a full week) → What If for every persona → drive reportOnlyFailure to zero → enforce ring by ring. Report-only alone isn’t sufficient because it samples sign-ins, not the silent ageing of the compliance bit — so you also confirm devices are actively checking in (recent Intune check-in), not merely nominally compliant, before enforcing.

These map to SC-300 (Identity and Access Administrator) — Conditional Access, device-based access, Intune compliance integration; MD-102 (Endpoint Administrator) — compliance policies, device enrolment, the MDE connector; and SC-200 (Security Operations Analyst) — the Defender for Endpoint risk signal. A compact cert map:

Question theme Primary cert Objective area
Compliant vs hybrid grant; CA design SC-300 Implement Conditional Access
Compliance policy authoring; actions/grace MD-102 Manage compliance policies
MDE risk connector + rule MD-102 / SC-200 Endpoint security; Defender integration
Filters for devices; extension attributes SC-300 Conditional Access assignments
App protection (MAM) vs device compliance MD-102 Manage app protection policies
Report-only / What If / rollout staging SC-300 Plan and implement CA

Quick check

  1. A fleet of hybrid-joined, non-Intune-enrolled domain PCs is entirely blocked after you enable a device grant. What grant did you pick, and what should it be?
  2. Where is the compliance “grace period” configured, and what value would you use during a rollout?
  3. Your Require compliant grant is on, but unmanaged laptops are getting in. What tenant setting is almost certainly the cause?
  4. A Windows device is Compliant in Intune but CA blocks it, and dsregcmd /status shows AzureAdPrt : NO. What’s wrong, and is the device actually noncompliant?
  5. You want to exempt kiosk devices (tagged extensionAttribute1 = "kiosk") from a require-compliant policy. Do you use an Include or an Exclude filter, and why?

Answers

  1. You picked Require device to be marked as compliant, which needs Intune enrolment — these devices were never enrolled, so isCompliant was never set and all are blocked. It should be Require compliant OR hybrid-joined with the OR operator, so the hybrid PCs pass on trustType = ServerAd while cloud-managed devices pass on compliance.
  2. In the compliance policy’s Actions for noncompliance tab, via the Mark device noncompliant action’s delay — there is no separate grace-period setting. Use 3 days during rollout so briefly-failing devices aren’t blocked instantly, then tighten later.
  3. The “Mark devices with no compliance policy assigned as: Compliant” tenant default (Compliance policy settings). Left at Compliant, unmanaged/unevaluated devices are treated as compliant and pass the grant. Set it to Not compliant (after your real policies are live).
  4. The Primary Refresh Token is missing, so the client can’t present the device’s state in the token request; CA sees an unknown device and blocks. The device is not actually noncompliant — its compliance is real, but the presentation of it failed. Re-trigger registration / fix time sync / re-authenticate to reissue the PRT.
  5. Use an Exclude filter with device.extensionAttribute1 -eq "kiosk". Filter Mode controls which devices the policy applies to: Exclude means “apply to everything except matched devices,” so kiosks fall out of enforcement while everyone else stays gated. An Include filter with the same rule would apply the policy only to kiosks and ungate every other device.

Glossary

Next steps

You can now build, scope, stage, and debug device-compliance gating end to end. Build outward:

Conditional AccessIntune ComplianceDevice FiltersEntra IDEndpointDefender for EndpointDevice ComplianceZero Trust
Need this built for real?

Vinod is a Senior Cloud Architect (22+ yrs) — available for Azure / AWS / GCP architecture, landing zones, and migrations.

Work with me

Comments

Keep Reading