A tenant can carry a dozen Conditional Access policies, a clean secure score, and a confident architecture diagram, and still hand an attacker a working session through a path nobody mapped. The exposure is rarely a missing rule. It is a rule that looks complete in the portal but never fires against the request that matters, because the request arrived over a protocol the policy was never asked to evaluate, or because two policies that each seemed sensible combined into a verdict neither author intended. Conditional Access is the gate that stands between a valid credential and a granted session, and the difference between a gate that protects and a gate that decorates comes down to whether the person who built it understood what the engine actually inspects before it decides.

That gap matters more in identity than almost anywhere else, because identity is the control plane an attacker reaches for first. A stolen password, a phished token, a reused credential from an unrelated breach: each of these is a knock at the gate, and the gate either asks for more proof or waves the request through. When the gate waves a stolen credential through, the blast radius is the entire reach of that identity, which for an administrator can mean the tenant itself. The cost of a Conditional Access misconfiguration is not measured in a slow page load. It is measured in whether an adversary who already holds a password is stopped at the threshold or seated at the desk.

Conditional Access deep dive on signals, grant and session controls, and policy gaps in Azure - Insight Crunch

This article treats Conditional Access as a design discipline rather than a checklist. The goal is to leave you able to reason about a policy the way the evaluation engine does: to know which signals it can read, which controls it can apply, how a set of policies resolves into a single grant or block, and where the quiet gaps hide. The organizing idea, the one to carry through every section, is what this series calls the signals-then-controls rule. Conditional Access matches signals and then applies controls, so a strong posture comes from pairing the right signals (risk, device state, location, application sensitivity) with the right controls (multifactor authentication, a compliant device requirement, a session limit), and the most common failure is an unblocked legacy-authentication path that ignores both halves of that pairing entirely.

To make the design concrete, the article centers on a named reference, the InsightCrunch Conditional Access pattern library, a small set of high-value policies with the signals each reads, the controls each applies, and the specific gap each one closes. The patterns are not exotic. They are the handful of policies that, assembled deliberately, turn a tenant from a collection of valid passwords into an environment where a valid password alone buys very little. The point of naming them is to move from inventing policies one alert at a time toward composing a baseline you can defend in a design review.

If you have already worked through the procedural side of this topic, this deep dive picks up where the steps leave off. The companion piece on how to configure Conditional Access policies covers the portal mechanics of building a single policy. Here the concern is the model underneath the mechanics: why the engine evaluates the way it does, and how that determines what you can and cannot enforce. Throughout, the article flags every limit and behavior that shifts as Azure changes, so you verify the current specifics against the official Microsoft documentation at the moment you build rather than trusting a value frozen in prose.

What problem does Conditional Access actually solve?

Conditional Access solves a problem that authentication alone cannot. Authentication answers whether a credential is valid. Conditional Access answers whether a valid credential, arriving in this context, should be trusted enough to proceed, and what additional proof the context demands first.

That distinction is the whole reason the control exists. A password, a certificate, or a token proves possession of a secret. Possession is necessary, but it is a weak signal on its own, because secrets leak. They are phished, reused across sites, harvested from infected machines, and replayed. If the only question the platform asks is whether the secret is valid, then every leaked secret is a granted session, and the defender has no second chance after the credential escapes. Conditional Access inserts that second chance. It treats a valid credential as the start of an evaluation, not the end of one, and it lets the request proceed only when the surrounding signals support trust.

The control sits at a precise point in the sign-in pipeline, and the placement is the key to understanding everything else about it. Conditional Access policies evaluate after primary authentication completes, not before and not during. The user (or the workload identity, or the device) first proves the credential to Microsoft Entra ID, and only once that primary proof succeeds does the policy engine wake up, gather the signals attached to the request, and decide what happens next. This ordering is exact and worth holding onto, because it explains both the power and the limits of the control. The power: by the time policy runs, the engine knows who is asking, from where, on what device, for which application, and with what risk attached, so it can make a contextual decision no static rule could. The limit: if a request reaches a resource without ever passing through the primary-authentication path that triggers policy evaluation, the policy never runs, and a gate that never runs protects nothing. That single limit is the seed of the most damaging Conditional Access gap, and the article returns to it in depth.

For the sign-in context that precedes policy, the deep dive on Microsoft Entra ID authentication traces the token flows and authentication methods that produce the primary proof Conditional Access then gates. Reading the two together gives the full picture: how identity is proven, and then how that proof is conditionally trusted.

How does the Conditional Access engine evaluate a request?

The engine evaluates every interactive sign-in as a small decision problem with two halves: first it decides whether a given policy applies to this request, and then, for the policies that apply, it decides what controls the request must satisfy. The mental model to hold is a pair of questions asked in order, assignment first and controls second.

The assignment half answers the question of scope. A policy carries a set of assignments that define the requests it cares about: which users and groups it targets, which cloud applications or actions it covers, and which conditions narrow it further (the platform, the location, the client app type, the device state, the risk attached to the sign-in). When a request arrives, the engine checks the request against each policy’s assignments. A policy whose assignments match the request is in scope and will contribute a verdict. A policy whose assignments do not match stays silent for this request. Nothing about the controls matters yet, because a control that belongs to a policy that does not apply has no effect.

The controls half answers the question of requirement. For every policy that is in scope, the engine reads the access controls the policy demands. Grant controls describe what the request must satisfy to be allowed through: complete multifactor authentication, come from a compliant or hybrid-joined device, use an approved client application, accept the terms of use, or some combination of those. A policy can also use the simplest grant control of all, which is to block access outright. Session controls describe how the resulting session behaves once granted: how often the user must reauthenticate, whether the browser session persists, whether app-enforced restrictions apply. The engine collects the controls from every in-scope policy and combines them.

Why do all matching policies apply together?

Because Conditional Access combines verdicts conservatively. Every policy whose assignments match the request contributes its controls, the engine takes the union of all grant requirements, and the user must satisfy all of them. A single block from any matching policy overrides every grant. There is no priority order that lets one policy quietly win over another.

This combination rule is the source of more surprise than any other part of the engine, so it rewards a careful reading. The engine does not pick the most specific policy, the most recently edited policy, or the policy with the strictest controls and apply that one alone. It applies every policy that matches, all at once. If three policies are in scope for a request and each demands multifactor authentication, the user authenticates once and satisfies all three, since the requirement is the same. If one of those three demands a compliant device instead, the user must now both complete multifactor authentication and present a compliant device, because the engine takes the union of requirements rather than the easiest. And if any single in-scope policy carries a block, the request is denied regardless of how many other policies would have granted it, because block is absolute. Grant controls negotiate; block ends the conversation.

Two further wrinkles complete the model. Within a single policy that lists several grant controls, the author chooses whether the controls combine with “require all” or “require one,” which changes whether the user must satisfy every listed control or just one of them. That choice lives inside one policy and does not extend across policies; across policies the union always governs. And exclusions behave differently from inclusions in a way that has real security weight: an excluded user, group, application, or location is removed from the policy’s scope entirely, so the policy never evaluates for them. Exclusions are how break-glass accounts stay reachable and how a specific service account avoids a control it genuinely cannot satisfy, but every exclusion is also a hole punched in the gate, and an exclusion that outlives its reason is a standing gap.

What does report-only mode change about evaluation?

Report-only mode changes the consequence, not the evaluation. A policy set to report-only is evaluated against every matching request exactly as an enabled policy would be, and the engine records what the verdict would have been, but it never enforces the controls. The user proceeds as if the policy did not exist while the logs capture the impact.

This is the single most useful safety mechanism the engine offers, and it deserves to be a reflex rather than an afterthought. Because the combination rule applies every matching policy and a block is absolute, a policy that looks correct in isolation can lock out a population the author never pictured: a service account that cannot do multifactor authentication, a region the author forgot held real users, a device platform that quietly fails the compliance check. Report-only mode lets the engine tell you the truth about scope before the truth becomes an outage. You enable the policy in report-only, watch the sign-in logs accumulate real verdicts against real traffic for a period long enough to cover the weekly and monthly rhythms of the tenant, confirm that the population it would have blocked or challenged is exactly the population you intended, and only then flip it to enabled. Skipping this step is how a Friday-evening policy change becomes a Saturday-morning incident.

What signals can Conditional Access read?

The strength of any Conditional Access design is bounded by the signals it pairs to its controls, so knowing the available signals precisely is the first half of the signals-then-controls rule. The engine can read a request along several independent dimensions, and a thoughtful policy reaches for the signal that most directly distinguishes a trustworthy request from a risky one rather than reaching for the same broad signal every time.

The most fundamental signal is identity itself: which user is signing in, and which groups and roles that user holds. This is the dimension every policy uses, because assignment to users and groups is how a policy chooses its population. A policy can target everyone, a single group, a directory role such as the privileged administrator roles, or a set of users with specific exclusions carved out. Targeting by directory role rather than by a hand-maintained group is the more durable choice for privileged populations, because role membership tracks the actual grant of privilege while a group can drift out of sync with who genuinely holds power in the tenant.

The application or action being requested is the second dimension. A policy can scope to specific cloud applications, to all applications, or to user actions such as registering security information or joining a device. Scoping by application is what lets a design demand more for a sensitive system than for a routine one, so that reaching the finance application or the administrative portals requires proof that reaching a low-sensitivity internal app does not. The granularity here is what turns a blunt tenant-wide rule into a graduated posture that asks for proof in proportion to what is at stake.

Which signals describe where and how the request arrives?

Location and client describe the request’s origin and channel. Location uses named network locations, often defined by IP ranges or by country, so a policy can treat a request from a known corporate network differently from one arriving from an unfamiliar region. The client app condition distinguishes modern browser and modern authentication clients from legacy authentication clients, which is the lever for the single most important gap-closing pattern in the library.

Location as a signal carries a caveat worth stating plainly, because it is a place designs go wrong. A network location is a statement about the IP address the request appears to come from, and an IP address is a weak proxy for trustworthiness on its own. Attackers route through residential proxies, compromised hosts, and infrastructure inside the regions a policy trusts, so a policy that grants extra trust to a “trusted” location is extending trust to anyone who can route through that location. Location is most defensible as a signal that adds friction to the unusual (challenge or block sign-ins from regions where the organization has no presence) rather than one that removes friction from the familiar (skip multifactor authentication because the request came from the office range). The asymmetry matters: tightening on unfamiliar locations costs an attacker something, while loosening on familiar ones hands them a target to impersonate.

The client app condition is quieter but more consequential. Modern authentication clients understand the full sign-in exchange, including the interactive challenges Conditional Access depends on to enforce multifactor authentication. Legacy authentication clients, the older protocols that predate modern authentication, often cannot present an interactive challenge at all. They send a username and password in a single exchange and expect a yes-or-no answer. A policy that depends on a grant control the legacy client cannot perform creates a fork: either the platform blocks the legacy client (good) or it falls back to evaluating the request without the control the client cannot do (the gap). This is why “block legacy authentication” is not a nice-to-have but a foundational pattern, and the article treats it as such.

How do risk signals change the picture?

Risk signals turn Conditional Access from a static set of rules into a system that responds to evidence. Identity Protection produces two risk dimensions, sign-in risk and user risk, that score the likelihood that a given sign-in or a given account is compromised, and a policy can read those scores as conditions and apply stronger controls when risk is elevated.

Sign-in risk is a real-time and near-real-time judgment about a particular authentication attempt. It rises when the attempt shows the fingerprints of compromise: an impossible travel pattern between two sign-ins, an anonymized network address, a sign-in from infrastructure associated with malicious activity, a token that shows signs of replay. The engine can read the sign-in risk level as a condition and gate the request accordingly, so a low-risk sign-in proceeds normally while an elevated-risk sign-in is challenged for multifactor authentication or blocked.

User risk is a slower, account-level judgment about whether the identity itself is likely compromised, accumulated from signals such as leaked credentials found in known breach corpora or a pattern of risky behavior over time. The natural control to pair with elevated user risk is a secure password change that forces the user to prove control of the account and rotate the credential, which both confirms the legitimate owner and invalidates the leaked secret. The pairing is the point: sign-in risk pairs with a step-up challenge for that session, user risk pairs with a credential reset for the account, and using the wrong control for the wrong risk either under-responds to a real compromise or over-burdens a clean account. The exact thresholds, the precise signals that feed each score, and the licensing that unlocks risk-based conditions all shift over time, so confirm the current behavior against the official Identity Protection documentation before you build a policy that leans on a specific risk level.

What controls can a policy apply?

If signals are the first half of the rule, controls are the second, and the art of Conditional Access is matching them. The engine offers two families of controls, grant controls that decide whether and under what proof a request is allowed, and session controls that decide how the granted session behaves, and a mature design uses both rather than treating every problem as something a grant control can solve.

Grant controls are the requirements a request must meet to proceed. The most familiar is requiring multifactor authentication, which forces a second proof beyond the password and defeats the large class of attacks that rest on a stolen password alone. Requiring a compliant device or a hybrid-joined device ties the grant to the health and management state of the machine, so that reaching a sensitive resource demands not just a valid user and a second factor but a device the organization actually governs. Requiring an approved client application or an application protection policy extends the same idea to mobile, binding access to apps that enforce data-handling rules. Requiring acceptance of a terms-of-use statement records informed consent before access. And the block control denies the request outright, which is the right tool when the goal is not to add friction but to close a path entirely.

A single policy can combine several grant controls and choose whether the user must satisfy all of them or any one of them. “Require all” is the conservative default for a sensitive scope: complete multifactor authentication and present a compliant device, both, before the finance application opens. “Require one” suits cases where either of two proofs is acceptable, such as accepting either a compliant device or a multifactor challenge for a moderately sensitive app. The choice is a deliberate statement about how much proof the resource warrants, and it should track the sensitivity of what the policy protects rather than defaulting to whatever is least disruptive.

When should a design reach for session controls instead?

Session controls are the right tool when the concern is not whether to grant access but how long and how freely the granted session should run. A grant control checks proof at the moment of sign-in; a session control governs the life of the session afterward, so it answers a different question and closes a different kind of exposure.

Sign-in frequency is the session control that bounds how long a single authentication remains good. Without it, a session token issued once can remain valid for an extended lifetime, which is convenient for the user and useful for an attacker who has stolen that token, because the stolen token keeps working until it expires on its own. Setting a sign-in frequency forces reauthentication on an interval, so the window during which a stolen session token is useful shrinks to the interval the policy sets. The trade-off is real: a short interval is more secure and more annoying, a long interval is the reverse, and the right setting depends on the sensitivity of the application and the tolerance of the people who use it. Sensitive administrative scopes justify a short interval that routine internal apps do not.

Persistent browser session is the companion control that governs whether a browser stays signed in across closures. Disabling persistence for sensitive scopes means a closed browser is a closed session, which matters on shared or unmanaged machines where a persistent session is a credential left on the desk. App-enforced restrictions hand the session’s behavior to the application itself, letting services such as Exchange and SharePoint limit what an unmanaged device can do within a granted session, for example allowing browser-based viewing while blocking download. The unifying idea across the session controls is that a grant is not a single yes but the opening of a session whose terms you can still set, and a design that stops thinking after the grant leaves that lever unused.

The InsightCrunch Conditional Access pattern library

The patterns below are the findable artifact of this article: a compact library of high-value policies, each expressed as a pairing of the signals it reads and the controls it applies, with the specific gap it closes. The library is the practical form of the signals-then-controls rule, and assembling these patterns deliberately is what turns a tenant into one where a valid password alone buys very little. The series maintains a broader, pattern-by-pattern treatment in the companion on Entra Conditional Access patterns; the table here is the design-review summary, the version you can defend in one screen.

Pattern Signals it reads Controls it applies Gap it closes
Administrator MFA Directory role membership (privileged roles), all apps Require multifactor authentication, require all A stolen admin password granting a session with no second proof
Block legacy authentication Client app type (legacy clients), all users, all apps Block access A protocol path that bypasses every interactive control
Require compliant device for sensitive apps Target application sensitivity, device compliance state Require compliant or hybrid-joined device Sensitive data reached from unmanaged, unhealthy machines
Risk-based step-up Sign-in risk level (medium and above) Require multifactor authentication An elevated-risk sign-in proceeding as if it were routine
User-risk remediation User risk level (high) Require secure password change A leaked or compromised credential staying live
Bound session for sensitive scopes Target application, device state Sign-in frequency, restrict persistent browser session A stolen session token usable for an extended window
Geographic blocking Named location (regions with no presence) Block access Unfettered sign-in attempts from regions the org never uses

The library reads as a progression rather than a menu. The first two patterns are the floor every tenant should reach: administrator multifactor authentication closes the highest-value single target, and blocking legacy authentication closes the path that would otherwise let an attacker sidestep that very control. Without the second pattern, the first is a wall with a side door. The middle patterns raise the proof in proportion to sensitivity, demanding a managed device where the data warrants it and stepping authentication up when the evidence of risk warrants it. The session patterns shorten the life of a granted session so a stolen token decays quickly. The geographic pattern adds friction to the implausible. None of these patterns is novel on its own; the value is in seeing them as a composed posture where each closes a gap the others leave open.

Why does the order of the library matter?

The order matters because the patterns protect one another. Administrator multifactor authentication is the highest-value control, but it is only as strong as the absence of a path around it, which is exactly what blocking legacy authentication provides. Building the second pattern before relying on the first is what keeps the first from being theater.

This interdependence is the reason a Conditional Access design is more than the sum of its policies. Consider the failure mode the order is built to prevent. A tenant enables administrator multifactor authentication and reports, accurately, that every privileged sign-in now requires a second factor through the modern authentication path. But legacy authentication remains unblocked, and a legacy protocol presents a username and password in a single exchange with no room for an interactive multifactor challenge. An attacker holding a stolen administrator password tries the legacy path, the platform has no way to challenge for the second factor that path cannot perform, and depending on configuration the request can proceed on the password alone. The multifactor policy was real, the second factor was enforced, and the account was still reachable with a password, because the protection and its protector were built out of order. The library is sequenced so that the path-closing patterns are in place before the proof-raising patterns are leaned on, and that sequencing is a design decision, not a portal detail.

How does least privilege apply inside Conditional Access?

Least privilege in Conditional Access is the discipline of scoping each policy to exactly the population and the conditions it needs to govern, and no wider, so that the gate asks for proof in proportion to what is at stake and grants no standing exemption it does not have to. The principle cuts in two directions at once: tighten controls where privilege is high, and resist exclusions that grant lasting freedom from those controls.

The tightening direction is the more visible one. The patterns in the library already express it: privileged roles carry the strongest grant controls, sensitive applications demand a managed device, and elevated risk triggers a step-up. Least privilege here means the strength of the control tracks the value of what it protects, so that a routine internal application is not burdened with the proof a finance system or an administrative portal genuinely needs, and the high-value targets are not left at the same low bar as everything else. A flat policy that applies the same control everywhere either over-burdens the routine or under-protects the sensitive, and usually both, because a single setting cannot be right for two populations with different stakes.

The resisting direction is the one designs neglect, and it is where least privilege does its quiet work. Every exclusion in a Conditional Access policy is a grant of privilege, the privilege of not being governed by that control, and like any privilege it should be minimal, justified, and time-bound. A service account excluded from a multifactor requirement because it cannot perform the challenge is a reasonable exclusion, but the exclusion should be as narrow as the account’s real need: scoped to that account, to that application, and revisited when the account’s purpose changes. The pattern that turns a reasonable exclusion into a standing risk is breadth and permanence: a group excluded “temporarily” that never gets reviewed, an exclusion that started for one account and grew to a dozen, a location exclusion that outlived the project that required it. Conditional Access exclusions are least-privilege decisions, and treating them as set-and-forget settings rather than grants that expire is how a clean policy accumulates holes.

This is also where Conditional Access connects to the wider least-privilege model of the tenant. Conditional Access governs the conditions of access; role-based and attribute-based access control govern the scope of what an identity can do once inside. The series treats that scope dimension in the comparison of Azure RBAC and ABAC, and the two disciplines reinforce each other: Conditional Access raises the bar for proving identity to a sensitive system, while least-privilege role assignment ensures that even a fully proven identity can touch only what its job requires. Neither substitutes for the other, and a design that hardens one while neglecting the other leaves the matching gap open.

Where do Conditional Access designs actually break?

Conditional Access designs break in a small number of recurring ways, and every one of them is a failure of the signals-then-controls pairing rather than a missing policy. Knowing the failure modes by name is what lets a reviewer look at a tenant full of confident-looking policies and find the gap that the policy count conceals.

The first and most damaging break is unblocked legacy authentication, and it earns its place at the top because it defeats controls that are otherwise correct. The mechanism was described above: legacy protocols cannot present the interactive challenge that grant controls such as multifactor authentication depend on, so a request over a legacy path can sidestep a control the modern path enforces. The danger is that the modern path looks fully protected, the dashboards are green, and the legacy path is invisible until someone goes looking for it. The fix is not to add another grant control but to close the path: block legacy authentication so there is no exchange that can dodge the challenge. This is the gap the namable claim warns about, and it is the first thing to check in any tenant that believes it has strong multifactor coverage.

What goes wrong when policies overlap?

Overlapping policies break designs by combining into verdicts neither author intended, because the engine applies every matching policy at once and takes the union of grant controls while letting any single block win outright. Two policies that each make sense alone can together lock out a population, or one author’s block can quietly override another’s carefully tuned grant.

The trouble with overlap is that the combined behavior is rarely visible from any single policy. An author edits one policy, confirms it does the right thing in isolation, and ships it, unaware that a second policy already in scope for the same population turns the combined requirement into something stricter than intended, or that a third policy’s block silences the grant entirely. The symptoms read as mysterious: a group that cannot reach an application despite a policy that should allow it, a population challenged for proof that no single policy seems to demand, a service account locked out by a rule that was never meant to touch it. The cause is almost always the combination rule meeting a tenant whose policies were authored independently over time. The discipline that prevents it is to reason about the whole policy set against a representative request rather than about one policy at a time, and the tool that makes that reasoning concrete is the What If evaluator, covered in the verification section, which shows exactly which policies apply to a described request and what the combined verdict would be.

Why is a missing break-glass account so dangerous?

A missing break-glass exclusion is dangerous because Conditional Access can lock out every administrator at once. If a policy change, an identity-provider outage, or a misconfigured control denies the very accounts that would fix it, and no account is excluded from that control, the tenant has no way back in through the front door. The lockout is total and self-inflicted.

This is the failure mode that turns a routine policy change into a crisis with no clean exit. Picture a tightened administrator policy that now requires a control which, due to an outage in the dependency that control relies on, no one can currently satisfy. Every administrator is held at the gate, including the administrators who would loosen the policy, and the loosening itself requires getting past the gate that is locked. The standard guard is a small number of break-glass (emergency access) accounts deliberately excluded from Conditional Access policies, held with long and protected credentials, monitored closely precisely because they bypass the controls, and used only when the normal path is unavailable. The exclusion is a calculated risk: these accounts are weaker by design, so they are watched harder, alerting on any use. The mistake tenants make is either omitting break-glass accounts entirely, which removes the recovery path, or creating them and then forgetting to exclude them from a new policy, which removes the recovery path just as effectively while leaving the comforting belief that it exists. Verifying that break-glass accounts remain excluded from every blocking policy is a standing check, not a one-time setup.

How do you verify a Conditional Access posture?

Verification is where a Conditional Access design stops being a claim and becomes a measured fact, and the engine offers three complementary tools for it: report-only mode to test a policy against real traffic before enforcing it, the What If evaluator to reason about how policies combine for a described request, and the sign-in logs to read what actually happened. A posture you have not verified with all three is a posture you are guessing about.

Report-only mode is the first line, and its role is to answer the question “what would this policy do to real traffic?” before that traffic feels any consequence. As described earlier, a report-only policy is evaluated exactly as an enabled one but never enforced, so the sign-in logs fill with the verdicts it would have produced. The verification discipline is to leave a new or changed policy in report-only long enough to span the tenant’s natural cycles, then read the logs to confirm that the population it would have challenged or blocked is precisely the population intended, with no surprise service account, no forgotten region, no device platform quietly failing. Only when the report matches the intent does the policy move to enabled. This single habit prevents the majority of self-inflicted lockouts.

How does the What If evaluator help?

The What If evaluator answers the combination question directly. You describe a hypothetical request (a user, an application, a location, a device state, a client app, a risk level) and the evaluator reports exactly which policies apply to that request and what the combined grant or block verdict would be. It makes the engine’s reasoning visible without touching a real sign-in.

This is the antidote to the overlap problem, because it forces the combined behavior into the open. Instead of reasoning informally about whether three independently authored policies will interact badly for a particular population, you describe that population’s request to the evaluator and read the answer. The evaluator shows the policies in scope, the controls each contributes, and the net verdict, which is exactly the information a single policy’s editing screen hides. Used before shipping a change, it catches the overlap that would otherwise surface as a mysterious lockout days later. Used during an incident, it explains why a particular request is being blocked or challenged when no single policy seems to demand it. The evaluator is a model of the engine, so it reflects the policies as configured rather than as imagined, which is precisely why it is trustworthy where intuition is not.

The sign-in logs are the third tool and the ground truth. Every interactive sign-in records which Conditional Access policies were evaluated, which applied, what controls they required, and whether the user satisfied them, so the logs are the authoritative account of what the gate actually did. Reading them is how you confirm that an enabled policy is firing as intended, how you discover a legacy-authentication path that the policy set is not catching, and how you investigate why a specific user hit a wall. The logs also feed the broader monitoring story: forwarding them to a central analytics workspace turns per-sign-in records into trends, so a rise in blocked legacy-authentication attempts or a spike in risk-based challenges becomes visible as a pattern rather than buried in individual events. The exact retention, the fields available, and the query surface evolve, so verify the current sign-in log schema and retention against the official documentation when you build alerting on it.

How do you make Conditional Access auditable and repeatable?

A Conditional Access posture that lives only as clicks in a portal is a posture no one can review, reproduce, or trust over time, so the final discipline is to make the policy set auditable and repeatable: expressed as code where practical, governed by regular review, and monitored so that drift surfaces as an alert rather than as an incident. The goal is a gate whose configuration is a known, version-controlled fact rather than an accumulation of forgotten edits.

Expressing policies as code is the foundation of repeatability. Conditional Access policies can be read and written through the Microsoft Graph API, which means the policy set can be exported to a definition, stored in source control, reviewed through the same pull-request process as any other infrastructure, and reapplied to rebuild or replicate the posture. The benefit is not only disaster recovery, though a code-defined posture is far easier to restore than a hand-clicked one. The larger benefit is that every change becomes visible and reviewable: a diff shows exactly what a proposed edit does to scope and controls, a reviewer can catch an overly broad exclusion before it ships, and the history records who changed what and when. A policy set under version control is a policy set whose surprises are caught in review rather than discovered in production.

The following sketch shows the shape of reading the current policy set through Graph for export and review. Treat command names, endpoints, and module versions as values to confirm against the current official documentation, since the Graph surface and its tooling change.

# Read the current Conditional Access policy set for export and review.
# Confirm cmdlet names and the required Graph scopes against current docs.
Connect-MgGraph -Scopes "Policy.Read.All"

# Retrieve all Conditional Access policies as objects.
$policies = Get-MgIdentityConditionalAccessPolicy

# Project the fields that matter for review: name, state, and the
# assignments and controls that define scope and requirement.
$policies | Select-Object DisplayName, State,
    @{ n = "IncludeUsers"; e = { $_.Conditions.Users.IncludeUsers } },
    @{ n = "ExcludeUsers"; e = { $_.Conditions.Users.ExcludeUsers } },
    @{ n = "Apps";         e = { $_.Conditions.Applications.IncludeApplications } },
    @{ n = "GrantControls"; e = { $_.GrantControls.BuiltInControls } } |
    ConvertTo-Json -Depth 5 |
    Out-File "./conditional-access-export.json"

The export is the input to two recurring disciplines. The first is review: walking the policy set on a schedule to confirm that every exclusion still has a reason, that break-glass accounts remain excluded from blocking policies, that no policy has drifted into a scope wider than intended, and that the named locations still describe the organization the tenant serves. An exclusion is a least-privilege grant, and like any grant it should expire unless renewed deliberately; the review is where that renewal happens or fails to. The second discipline is monitoring drift: comparing the live policy set against the version-controlled definition so that an out-of-band change, whether an accident or an intrusion, shows up as a difference rather than hiding. A gate whose configuration is monitored is a gate that tells you when it has been altered, which is the difference between catching a quiet weakening early and discovering it after it has been used.

How does this fit the wider Zero Trust posture?

Conditional Access is the identity gate within a Zero Trust posture, and making it auditable connects it to the rest of that posture. Zero Trust treats identity as the primary perimeter and assumes breach, so a verifiable, version-controlled, monitored identity gate is exactly the kind of control the model asks for, rather than a static wall trusted on faith.

Seen this way, the disciplines in this article are not housekeeping but the concrete expression of a principle. Verify explicitly: Conditional Access evaluates signals on every request rather than trusting a prior decision. Use least privilege: policies scope controls to what each population warrants and treat exclusions as grants that expire. Assume breach: session controls shorten the life of a stolen token, risk signals respond to evidence of compromise, and monitoring surfaces drift before it is exploited. The broader mapping of these principles to concrete Azure controls is the subject of the series piece on Azure Zero Trust architecture, which places Conditional Access alongside network segmentation, least-privilege role assignment, and assume-breach monitoring as the identity layer of the whole. A Conditional Access design that is verifiable and repeatable is the part of Zero Trust that actually holds, because it is the part you can prove is doing what you believe it does.

To move from reading to doing, model these policies and watch them behave against real traffic before you enforce them. You can run the hands-on Azure labs and command library on VaultBook to build a policy in report-only, read its verdicts in the sign-in logs, and use the What If evaluator against a described request, so the engine’s behavior becomes something you have observed rather than something you have only read about.

How does device compliance work as a signal?

Device compliance is one of the strongest signals a policy can read, because it ties access not to something a person knows or holds but to the health and management state of the machine the request comes from, which is far harder for an attacker to fake than a password or a location. Understanding where the compliance verdict comes from is what lets a design use it deliberately rather than turning it on and hoping.

The compliance signal does not originate inside Conditional Access. It is produced by the device management layer, which evaluates each enrolled device against a set of compliance rules (an encrypted disk, a current operating-system version, a screen lock, the absence of a known threat, and so on) and stamps the device as compliant or not. Conditional Access then reads that stamp as a condition. The separation is the point: the policy engine does not inspect the device itself, it trusts the management layer’s verdict about the device, which means the device must be enrolled in management and actively reporting its state for the signal to mean anything. A device that is unmanaged is not “non-compliant” in a useful sense; it is unevaluated, and a policy that requires a compliant device will simply block it, which is usually the intended outcome for a sensitive resource but a surprise if a population was never enrolled.

A related grant control accepts a hybrid-joined device, which trusts a machine that is joined to both the on-premises directory and Microsoft Entra ID, a common state for organizations partway through a cloud transition. The difference between requiring a compliant device and requiring a hybrid-joined one is the difference between trusting an active health verdict and trusting a join relationship, and the right choice depends on how the organization manages its fleet. The series covers the management mechanics that produce the compliance verdict elsewhere; for the purpose of this design, the signal to internalize is that device state is a strong condition precisely because it reflects something the organization actively governs rather than something a credential holder can assert.

Why is device compliance harder to spoof than location?

Device compliance is harder to spoof because it reflects an active management relationship rather than a network claim. A location signal asserts where a request appears to come from, which an attacker can manipulate by routing through trusted infrastructure. A compliance signal asserts that a managed device reported a healthy state to the organization, which an attacker without that managed device cannot reproduce.

This asymmetry is why a graduated design tends to reach for device compliance on its most sensitive scopes while using location only to add friction to the implausible. An attacker who has phished a password and a one-time multifactor code has defeated two signals that rest on what the user knows and receives, but has not thereby obtained a managed, enrolled, healthy corporate device reporting to the organization’s management layer. Requiring that device for the finance application or the administrative portals raises the cost of an attack from “phish a credential and a code” to “phish a credential and a code and also possess a governed device,” which is a categorically larger barrier. The trade-off is operational rather than security-related: the requirement only works where the population is enrolled, so a device-compliance policy is as much a statement about the maturity of the device fleet as about the sensitivity of the resource, and rolling it out demands confirming enrollment coverage first to avoid blocking legitimate users who were never managed.

Six scenarios a Conditional Access design has to handle

The recurring cases engineers report are not exotic edge conditions; they are the situations a competent design anticipates and answers in advance. Each one is best read as a pattern the design addresses, a pairing of the signal that distinguishes the situation from a routine request and the control that responds to it. Walking the six together shows how the pattern library behaves when it meets the messiness of a real tenant rather than a diagram.

The first scenario is legacy authentication bypassing multifactor authentication until it is explicitly blocked. An engineer enables a multifactor requirement, confirms in the sign-in logs that browser-based sign-ins now complete a second factor, and reasonably concludes the account is protected. Then a report surfaces a successful sign-in that completed with a password and no second factor, arriving over an older mail or client protocol. What happened is the fork described earlier: the legacy protocol could not present the interactive challenge, and the request resolved on the credential alone. The pattern that addresses it is not a stronger multifactor policy but a separate policy that blocks legacy authentication outright, removing the path that the challenge could not traverse. The lesson the scenario teaches is that a control is only as strong as the absence of a path around it, which is why this pattern sits near the floor of the library.

The second scenario is a risk-based policy stepping up authentication when the evidence warrants it. A user signs in normally most days, and the sign-in proceeds with the proof the baseline requires. One day the same account signs in from an anonymized network shortly after a sign-in from a distant region, a pattern that has the fingerprints of compromise. Identity Protection raises the sign-in risk for that attempt, a policy reads the elevated risk as a condition, and the engine challenges the request for multifactor authentication that the routine sign-in did not face. If the legitimate user is behind it, the challenge is a brief friction; if an attacker is behind it, the challenge is a wall the stolen password cannot climb. The pattern pairs the sign-in-risk signal with a step-up grant control, responding to evidence rather than treating every sign-in identically.

How does a design handle device compliance and session limits together?

A mature design handles them as complementary patterns: device compliance gates whether a sensitive session opens at all, and session controls govern how that session behaves once open. The first answers who may enter, the second answers how long and how freely they may stay, and a sensitive scope often warrants both because each closes an exposure the other leaves open.

The third scenario is a device-compliance requirement for a sensitive application. A finance system holds data that must not be reached from an unmanaged personal laptop, so the design scopes a policy to that application and requires a compliant or hybrid-joined device. A user on a governed corporate machine reaches the application without friction because the device reports compliant; the same user on a personal device is blocked, because that device is unevaluated by the organization’s management layer. The pattern pairs the application-sensitivity signal with the device-state control, closing the gap where valuable data is reachable from machines the organization cannot patch, monitor, or wipe. The scenario also surfaces the operational caveat: the requirement assumes the legitimate population is enrolled, so the rollout confirms enrollment coverage before enforcement to avoid blocking real users.

The fourth scenario is session controls limiting how long a single authentication stays good. Without a sign-in frequency, a session token granted once can remain valid for an extended lifetime, which is convenient until that token is stolen, after which it remains useful to the thief until it expires on its own. The design scopes a sign-in frequency to its sensitive applications so a session must reauthenticate on an interval, shrinking the window during which a stolen token works to the length of that interval. For shared or unmanaged machines, the design also disables persistent browser session, so a closed browser is a closed session rather than a credential left waiting on the desk. The pattern pairs the application signal with session controls, accepting a measured amount of user friction in exchange for a session that decays rather than lingering.

The fifth scenario is overlapping policies producing unexpected results. A tenant accumulates policies over time, authored by different people for different reasons, and one day a population cannot reach an application that a policy plainly seems to allow, or is challenged for proof that no single policy appears to demand. The cause is the combination rule meeting independent authorship: every matching policy applies at once, grant requirements take the union, and any single block wins outright, so the combined verdict is something no individual author pictured. The pattern that addresses it is procedural rather than a policy: reason about the whole set against a representative request using the What If evaluator before shipping a change, so the combined behavior is visible in advance rather than discovered as a mysterious lockout. The scenario is a reminder that a Conditional Access posture is the behavior of the set, not the sum of its policies read one at a time.

The sixth scenario is a missing break-glass exclusion turning a routine change into a crisis. A tightened administrator policy now requires a control that, because of a dependency outage, no one can currently satisfy, and every administrator is held at the gate, including the administrators who would loosen the policy. If no account was excluded from the control, there is no way back in through the front door, and the lockout is total and self-inflicted. The pattern that addresses it is the deliberate maintenance of a small number of emergency-access accounts excluded from blocking policies, held with long protected credentials and watched closely precisely because they bypass the controls. The scenario underscores that the recovery path is not automatic; it is a design decision that must be made before it is needed and verified against every new blocking policy thereafter.

How do you sequence a Conditional Access rollout?

Sequencing a rollout is the difference between a posture that hardens steadily and one that locks out a population on its first enforced policy, and the sequence follows directly from how the engine combines verdicts. Because every matching policy applies at once and a block is absolute, the order in which controls reach enforcement, and the care taken at each step, determines whether the tenant tightens safely or trips over its own rules.

The first principle of sequencing is that path-closing patterns precede proof-raising patterns. Blocking legacy authentication closes the route that would otherwise let an attacker sidestep an interactive control, so it belongs near the start of a rollout rather than after the multifactor policies it protects. Building the proof-raising patterns first and the path-closing ones later leaves a window in which the stronger controls are quietly bypassable, which is precisely the window an attacker holding a stolen credential would exploit. Closing the path first means that when the proof-raising patterns arrive, they arrive into an environment where there is no exchange that can dodge them.

The second principle is that every policy enters through report-only mode before it enforces. A new or changed policy goes live in report-only, the sign-in logs accumulate the verdicts it would have produced against real traffic for a period long enough to span the tenant’s weekly and monthly rhythms, and only once the affected population matches the intent does the policy flip to enabled. This is not a formality to skip when a change feels obviously correct, because the failure mode is exactly the change that feels obviously correct and quietly catches a service account, a forgotten region, or an unenrolled device platform. Report-only mode converts the cost of that error from an outage into a log entry.

Why does policy naming and structure matter for a rollout?

Policy naming and structure matter because a posture you cannot read is a posture you cannot safely change. A consistent naming convention that encodes the target population, the scope, and the control lets a reviewer understand the set at a glance, and a deliberate structure of focused policies rather than sprawling ones keeps the combination behavior predictable when a new policy is added.

The discipline here is to prefer a set of focused policies, each expressing one clear intent, over a few sprawling policies that try to encode many decisions at once. A focused policy is easy to reason about in isolation and easy to predict in combination, while a sprawling policy hides its interactions inside its own complexity and surprises the next author who edits near it. A naming convention reinforces this: when a policy’s name states who it targets, what it covers, and what it requires, the set becomes self-documenting, and the What If evaluator’s output becomes legible because the policy names that appear in it carry meaning. Structure and naming are not cosmetic; they are what make the combination rule’s behavior foreseeable as the set grows, and a rollout that neglects them accumulates a posture that works today and confuses everyone who touches it tomorrow. The procedural mechanics of building each policy in the portal are covered in the companion on how to configure Conditional Access policies; the sequencing and structure above are what turn those individual builds into a coherent posture.

How do you protect the registration of security information?

A subtle but consequential gap sits at the moment a user registers their security information, the multifactor methods and recovery details an account relies on, because the registration itself is a privileged action that an attacker who has stolen a password will try to perform. If anyone holding a valid password can register a new multifactor method unchallenged, then the multifactor requirement protecting every other action can be undermined by an attacker who simply enrolls their own second factor first.

The exposure works like this. An attacker phishes a password for an account that has not yet registered any multifactor method, or whose registration is not itself protected. The attacker signs in, is prompted to register security information because the account needs a second factor, and registers a method under the attacker’s control. From that point the attacker holds both the password and a valid second factor, and the multifactor requirement that was meant to stop them now waves them through, because they satisfy it with the factor they enrolled. The control intended to protect the account became the mechanism the attacker used to capture it, all because the act of registration was left unguarded.

The pattern that addresses this scopes a Conditional Access policy to the user action of registering security information and applies a control proportionate to the risk, commonly requiring the registration to occur from a trusted condition such as a known location or a managed device, or under a stronger initial verification, so that an attacker holding only a stolen password cannot complete the enrollment. The principle generalizes beyond this one action: any privileged self-service action that can weaken an account’s protection deserves a control on the action itself, not only on the resources the account later reaches. A design that protects every application but leaves the bootstrapping of the account’s own credentials open has guarded the rooms while leaving the key-cutting machine unattended. Confirm the current set of user actions a policy can target against the official documentation, since the available actions expand over time, and treat the protection of credential registration as part of the floor rather than an advanced refinement.

How do guest and external users change a Conditional Access design?

Guest and external identities change the calculus because they are people the organization does not employ, manage, or fully control, yet they hold a foothold in the tenant for collaboration, and a design that treats them identically to employees either over-trusts outsiders or burdens its own staff with controls aimed at someone else. A deliberate design distinguishes the two populations and scopes its requirements to each.

The first thing to recognize is that an external guest brings their own identity and their own posture, much of which the host organization cannot see or govern. The host cannot enroll the guest’s device in its management layer, cannot enforce its password rules on the guest’s home directory, and cannot vouch for the guest’s own multifactor hygiene unless it requires proof at the door. This is why a common and sensible pattern requires guests to satisfy a multifactor challenge issued by the host tenant rather than trusting whatever the guest’s home directory may or may not have enforced. The host cannot manage the guest’s device, but it can insist that reaching the host’s resources demands a second factor proven to the host, which closes the gap where a guest account compromised in its home directory becomes a quiet entry into the host tenant.

The second consideration is scope. Because the engine assigns policies by user and group, a design can target external identities as a population distinct from internal users, applying controls that fit an outsider’s relationship to the tenant. A guest might be permitted to reach a specific collaboration application under a multifactor requirement while being blocked from everything else, which both serves the collaboration and contains the guest’s reach to what the relationship actually needs. This is least privilege applied at the level of the whole identity rather than a single role: the external user is granted a narrow, conditioned path rather than a general presence.

Should guests face the same controls as employees?

Guests should face controls suited to their relationship, not a copy of the employee posture. Some employee controls, such as requiring a managed device, cannot apply to a guest whose device the host does not govern, while others, such as requiring a host-issued multifactor challenge and confining the guest to specific applications, fit the external relationship precisely. The design matches the control to what the host can actually verify and govern.

Applying an employee-shaped control to a guest tends to fail in one of two directions. Requiring a managed device from a guest whose laptop the host cannot enroll simply blocks the guest, defeating the collaboration the guest was invited for, because the device is unevaluated by the host’s management layer rather than non-compliant in any actionable sense. Conversely, granting a guest the same broad reach an employee holds, on the assumption that the guest’s home directory must have enforced something, extends trust the host cannot confirm. The middle path is to require of guests what the host can prove at its own door, a multifactor challenge issued by the host, and to confine them to the applications the relationship needs, while reserving device-state and management-based controls for the internal population those controls can actually evaluate. The broader treatment of guest and location handling lives in the series companion on Entra Conditional Access patterns, which assembles the external-identity patterns into the wider baseline.

What does Conditional Access not do?

A clear-eyed design knows the boundaries of the control as well as its powers, because the gaps that hurt most are the ones where a team believed Conditional Access covered something it never touched. The control gates the conditions under which an authenticated identity proceeds; it is not an authorization system, not a network firewall, and not a guarantee against every path to a resource.

Conditional Access does not decide what an identity is allowed to do once it is inside, only whether and under what proof it gets in. The scope of an identity’s permissions, which resources it can read or change, is the domain of role-based and attribute-based access control, and a strong conditional gate in front of an over-privileged identity still over-exposes the tenant the moment that identity is granted. This is why the discipline pairs Conditional Access with least-privilege role assignment rather than treating either as sufficient: one governs the conditions of entry, the other governs the reach after entry, and a design that hardens one while neglecting the other leaves the matching half open. The point is worth restating because it is a common misconception that a tightly conditioned sign-in implies a tightly bounded session; it does not, and the two must be designed together.

Conditional Access also does not inspect the content of what happens inside a granted session beyond the session controls it sets. Once a session is granted, the per-action behavior is governed by the application and by the permissions the identity holds, not by the conditional gate, which stepped aside the moment it granted the session under whatever session terms it imposed. Session controls bound the life and the persistence of the session and can hand certain restrictions to the application, but they are not a data-loss-prevention system or an inline inspector of every request the session makes. Treating Conditional Access as if it watches the session continuously overstates it; what it does is decide the terms at the gate and bound the session’s lifetime, after which other controls carry the load.

Why is the authentication path the boundary that matters most?

The authentication path is the boundary that matters most because Conditional Access only governs requests that pass through the primary-authentication evaluation that triggers it. A request that reaches a resource without traversing that path is never gated, which is exactly why an unblocked legacy-authentication route is so dangerous: it is not that the policy decided to allow the request, but that the policy never ran.

This is the boundary that turns an abstract limit into the concrete gap the whole article circles back to. The control is effective precisely because it evaluates rich context after primary authentication, and it is limited for the same reason: its power exists only on the path where that evaluation happens. Any route that delivers a request to a resource without invoking the evaluation, whether an older protocol that authenticates outside the interactive flow or a configuration that skips the conditional check, is a route on which the gate is not merely lenient but absent. A design that maps its protections by listing the policies it has built, without asking which request paths actually invoke those policies, measures the wrong thing. The right question is not “how many policies protect this resource” but “is there any path to this resource that does not pass through them,” and closing the paths that answer yes is the work that makes the policies real. This is the boundary that the namable claim names and the pattern library is sequenced to defend.

What is the minimum viable Conditional Access baseline?

A tenant starting from nothing does not need every pattern at once; it needs a small floor that closes the largest exposures first, and naming that floor explicitly prevents the paralysis of treating a hardening project as all-or-nothing. The minimum viable baseline is the subset of the pattern library that buys the most security per policy, built in an order that keeps each policy from undermining the next.

The floor begins with closing the path that defeats interactive controls. Blocking legacy authentication comes first because every proof-raising control that follows depends on the absence of a route that can sidestep it, and building the multifactor requirement before this path is closed leaves that requirement quietly bypassable. With the path closed, the next layer raises proof where the stakes are highest: a multifactor requirement on the privileged directory roles, because a compromised administrator is the worst single outcome a tenant can suffer and the second factor is the control that most directly defeats the stolen-password attack against it. These two together, a path closed and the highest-value accounts hardened, are the irreducible start, and a tenant that has only these two has already moved a large distance from a posture where a valid password alone opens the door.

The baseline then extends to the rest of the population and the bootstrapping of accounts. A multifactor requirement broadened beyond administrators to the general user population raises the floor for everyone, and a control on the registration of security information protects the act of enrolling a second factor so an attacker holding only a stolen password cannot enroll their own. Alongside these sits the recovery path that makes the whole baseline safe to operate: a small number of emergency-access accounts excluded from the blocking policies, held with long protected credentials and watched closely, so that a future tightening or a dependency outage cannot lock every administrator out at once. None of these requires a mature device fleet or a risk-detection license, which is why they form the floor rather than the ceiling.

Above the floor, the design grows toward the rest of the library as the tenant matures: device-compliance requirements as the fleet becomes enrolled, risk-based step-up as risk detection becomes available, session controls as the sensitivity of specific applications justifies bounding their sessions, and geographic blocking where the organization’s footprint makes it meaningful. The progression is deliberate. Each addition closes a gap the floor leaves open, and each is verified in report-only mode before it enforces, so the posture hardens in steps that can each be confirmed rather than in one change that risks everything. The minimum viable baseline is not a compromise; it is the foundation the rest of the design is built on, and naming it turns an intimidating project into a sequence a team can actually execute.

The verdict on Conditional Access as a discipline

Conditional Access rewards the engineer who treats it as a design problem and punishes the one who treats it as a checklist, and the difference is the signals-then-controls rule. A strong posture is not a count of policies but a set of deliberate pairings: the right signal read against the right control, with the path-closing patterns in place before the proof-raising patterns are leaned on, and with every exclusion understood as a least-privilege grant that expires rather than a permanent setting. The tenant that reaches that posture is one where a valid password alone, the thing an attacker is most likely to hold, buys very little.

The one gap to carry away above all others is the unblocked legacy-authentication path, because it is the gap that defeats good controls silently. A tenant can enforce multifactor authentication everywhere on the modern path, show a clean secure score, and still be reachable with a password over a protocol that cannot be challenged. Blocking legacy authentication is the pattern that makes every other pattern real, which is why the library is sequenced to put it near the floor. Build the path-closing patterns first, raise proof in proportion to sensitivity, bound the session so a stolen token decays, respond to risk with evidence, and verify the whole with report-only mode, the What If evaluator, and the sign-in logs before you trust it. A gate built and verified that way is the identity perimeter a Zero Trust posture depends on, and it is the difference between a credential that opens the tenant and a credential that opens almost nothing.

Frequently asked questions

How does Conditional Access actually work?

Conditional Access works as a policy engine that evaluates every interactive sign-in after primary authentication succeeds. The user first proves a credential to Microsoft Entra ID, and only once that proof completes does the engine wake up, check the request against each policy’s assignments to decide which policies are in scope, and then apply the access controls those in-scope policies demand. It combines verdicts conservatively: it takes the union of every matching policy’s grant requirements and lets any single block override every grant. The result is a contextual decision that a static rule could not make, because by evaluation time the engine knows who is asking, from where, on what device, for which application, and with what risk attached. The key constraint is the timing: a request that never passes through the primary-authentication path that triggers evaluation is never gated.

What signals and risk does Conditional Access evaluate?

Conditional Access reads a request along several independent dimensions. Identity comes first: which user, group, and directory role is signing in, which is how a policy chooses its population. The application or user action being requested lets a policy demand more for a sensitive system than a routine one. Location uses named network locations to distinguish familiar origins from unfamiliar regions, though an IP address is a weak proxy for trust on its own. The client app condition separates modern authentication clients from legacy ones, which is the lever behind the most important gap-closing pattern. On top of these, Identity Protection contributes two risk dimensions: sign-in risk, a near-real-time judgment about a specific attempt, and user risk, a slower account-level judgment about likely compromise. A policy can read those scores as conditions and apply stronger controls when risk is elevated. The precise signals and thresholds shift, so confirm them against current documentation.

What grant and session controls are available?

Grant controls decide whether and under what proof a request proceeds. They include requiring multifactor authentication, requiring a compliant or hybrid-joined device, requiring an approved client app or app protection policy, requiring acceptance of a terms-of-use statement, and the block control that denies access outright. A single policy can combine grant controls with require-all or require-one logic, a deliberate choice that should track the sensitivity of what the policy protects. Session controls govern how a granted session behaves rather than whether it is granted. Sign-in frequency bounds how long one authentication remains valid, which shrinks the window a stolen session token stays useful. Restricting persistent browser session means a closed browser is a closed session, which matters on shared machines. App-enforced restrictions hand session behavior to services such as Exchange and SharePoint, allowing limited actions on unmanaged devices. A mature design uses both families rather than solving everything with a grant.

What are the most common Conditional Access patterns?

The high-value patterns form a progression. Administrator multifactor authentication targets privileged directory roles and requires a second factor, closing the highest-value single target. Blocking legacy authentication targets legacy client protocols and blocks them, closing the path that would otherwise sidestep interactive controls. Requiring a compliant device for sensitive applications ties access to a managed, healthy machine. Risk-based step-up reads an elevated sign-in risk and demands multifactor authentication for that session. User-risk remediation reads a high user-risk score and forces a secure password change to invalidate a leaked credential. Bounding the session with a sign-in frequency and restricted persistence shortens the life of a stolen token. Geographic blocking denies sign-ins from regions where the organization has no presence. The InsightCrunch pattern library presents these as a composed posture where each closes a gap the others leave open, rather than a menu to pick from.

How does Conditional Access fit Zero Trust?

Conditional Access is the identity gate of a Zero Trust posture, and it implements all three Zero Trust principles concretely. Verify explicitly: the engine evaluates signals on every interactive request rather than trusting a prior decision, so access is earned again each time rather than granted once. Use least privilege: policies scope controls to what each population genuinely warrants, demanding more for privileged roles and sensitive applications, and treat every exclusion as a grant that should be minimal and time-bound. Assume breach: session controls shorten the useful life of a stolen token, risk signals respond to evidence of compromise as it appears, and monitoring the policy set surfaces drift before it is exploited. Zero Trust moves the perimeter from the network to identity, which makes a verifiable, version-controlled, monitored identity gate exactly the control the model depends on. Conditional Access is the part of that model you can prove is working.

What are the most common Conditional Access gaps?

Three gaps recur. The first and most damaging is unblocked legacy authentication: legacy protocols cannot present the interactive challenge that grant controls depend on, so a request over a legacy path can sidestep a control the modern path enforces, while the dashboards stay green. The fix is to close the path by blocking legacy authentication, not to add another grant control. The second is overlapping policies that combine into verdicts neither author intended, because the engine applies every matching policy at once and a single block overrides every grant. The What If evaluator makes the combined behavior visible before it surfaces as a mysterious lockout. The third is a missing or forgotten break-glass exclusion, which can lock out every administrator at once if a control becomes unsatisfiable, leaving no recovery path. Each gap is a failure of the signals-then-controls pairing rather than a missing policy, and each is found by reasoning about the whole set.

Why does blocking legacy authentication matter so much?

Blocking legacy authentication matters because it is the pattern that makes every other pattern real. Legacy protocols predate modern authentication and often cannot present an interactive challenge, so they send a username and password in one exchange and expect a yes-or-no answer. A grant control such as multifactor authentication needs the interactive exchange that legacy clients cannot perform, which creates a fork: either the platform blocks the legacy client or it evaluates the request without the control the client cannot do. When legacy authentication is unblocked, an attacker holding a stolen password can try the legacy path and proceed on the password alone, even in a tenant that enforces multifactor authentication everywhere on the modern path. The protection looks complete and is quietly defeated. This is why the pattern library sequences blocking legacy authentication near the floor: an administrator multifactor policy with an open legacy path is a wall with an unguarded side door.

What is report-only mode and when should I use it?

Report-only mode evaluates a policy against every matching request exactly as an enabled policy would, records what the verdict would have been, and never enforces the controls. The user proceeds as if the policy did not exist while the sign-in logs capture its impact. Use it as a reflex for every new or changed policy, not as an occasional precaution. Because the engine applies all matching policies and a block is absolute, a policy that looks correct in isolation can lock out a population the author never pictured: a service account that cannot perform multifactor authentication, a forgotten region, a device platform that fails compliance. Report-only mode tells you the truth about scope before that truth becomes an outage. Leave the policy in report-only long enough to span the tenant’s weekly and monthly rhythms, read the logs to confirm the affected population matches your intent, and only then enable it. This single habit prevents most self-inflicted lockouts.

How do I avoid locking myself out with a Conditional Access policy?

Avoiding lockout rests on two practices used together. First, maintain a small number of break-glass (emergency access) accounts that are deliberately excluded from Conditional Access policies, held with long protected credentials, and monitored closely precisely because they bypass controls. They are your recovery path when a policy change or a dependency outage makes a control unsatisfiable for everyone else. The common mistake is creating them once and then forgetting to exclude them from a newly added blocking policy, which removes the recovery path while leaving the belief that it exists. Verifying break-glass exclusions against every blocking policy is a standing check. Second, use report-only mode on every change and read the resulting verdicts before enforcing, so the population a policy would block is confirmed before it is blocked. Together these mean a policy mistake degrades to a logged near-miss rather than a tenant-wide lockout with no way back in.

What is the difference between sign-in risk and user risk?

Sign-in risk and user risk are two distinct judgments from Identity Protection that pair with different controls. Sign-in risk is a near-real-time assessment of a particular authentication attempt, rising when the attempt shows fingerprints of compromise such as impossible travel, an anonymized network address, or signs of token replay. Its natural control is a step-up challenge for that session, typically requiring multifactor authentication, so a risky attempt must prove more while a routine one proceeds. User risk is a slower, account-level assessment of whether the identity itself is likely compromised, accumulated from signals such as credentials found in known breach corpora. Its natural control is a forced secure password change, which both confirms the legitimate owner and invalidates the leaked secret. Using the wrong pairing misfires: a credential reset for a one-off risky sign-in over-burdens a clean account, while a session challenge for a known-leaked credential leaves the leaked secret live. Match the control to the kind of risk.

Can Conditional Access enforce multifactor authentication on its own?

Conditional Access can require multifactor authentication as a grant control, but the requirement only holds on a request path that the engine actually evaluates and that can perform an interactive challenge. This is the distinction that trips up tenants. On the modern authentication path, requiring multifactor authentication works as expected: the user completes a second proof before the grant. But a request over a legacy protocol that cannot present an interactive challenge does not get challenged, and depending on configuration may proceed without the second factor. So Conditional Access enforces multifactor authentication reliably only when paired with a policy that blocks the legacy paths that would otherwise bypass it. The lesson is that a grant control is not self-sufficient; it depends on the absence of a path that can dodge it. Enforcing multifactor authentication is therefore two patterns working together, the requirement and the path-closing block, not a single setting.

How do overlapping Conditional Access policies cause problems?

Overlapping policies cause problems because the engine applies every policy whose assignments match a request, takes the union of all grant requirements, and lets any single block override every grant. The combined behavior is rarely visible from any one policy’s editing screen. An author confirms a policy is correct in isolation and ships it, unaware that a second in-scope policy turns the combined requirement stricter than intended, or that a third policy’s block silences the grant. The symptoms read as mysteries: a group that cannot reach an app a policy should allow, a population challenged for proof no single policy demands, a service account locked out by a rule never meant to touch it. The discipline that prevents this is reasoning about the whole policy set against a representative request rather than one policy at a time, and the What If evaluator makes that concrete by reporting which policies apply to a described request and what the combined verdict would be.

Should I use location as a Conditional Access signal?

Location is useful as a signal but only with a clear understanding of its asymmetry. A named network location is a statement about the IP address a request appears to come from, and an IP address is a weak proxy for trustworthiness because attackers route through residential proxies, compromised hosts, and infrastructure inside the regions you trust. The defensible use of location adds friction to the unusual: challenging or blocking sign-ins from regions where the organization has no presence costs an attacker something. The risky use removes friction from the familiar: skipping multifactor authentication because a request came from the office range hands an attacker a location to impersonate and a control to bypass. Tightening on unfamiliar locations is sound; loosening on familiar ones is a target. Treat location as a way to raise the bar for the implausible, not as a way to lower it for the routine, and never as a substitute for a stronger signal like device compliance or risk.

How do I make sensitive applications require a managed device?

Requiring a managed device for a sensitive application pairs an application-scope signal with a device-state grant control. You scope a policy to the target application or set of applications, and you require a compliant device or a hybrid-joined device as the grant control, so that reaching that application demands not only a valid user and any other required proof but a machine the organization actually governs. This closes the gap where sensitive data is reachable from unmanaged, unhealthy, or personal machines that the organization cannot patch, monitor, or wipe. The compliance signal comes from device management, so the device must be enrolled and reporting its state for the control to evaluate meaningfully. Combine this with require-all logic when the application warrants both a managed device and multifactor authentication, which is common for finance systems and administrative portals. As always, test the policy in report-only first, because a device-compliance requirement can surprise you with platforms or populations that are not yet enrolled.

How do I verify that my Conditional Access policies work as intended?

Verification uses three complementary tools, and a posture confirmed by all three is one you can trust. Report-only mode tests a new or changed policy against real traffic without enforcing it, so the sign-in logs fill with the verdicts it would have produced and you can confirm the affected population matches your intent before enabling. The What If evaluator answers the combination question: you describe a hypothetical request and it reports exactly which policies apply and what the combined grant or block verdict would be, which exposes overlap before it becomes a lockout. The sign-in logs are the ground truth, recording for every interactive sign-in which policies were evaluated, which applied, what they required, and whether the user satisfied them, so you can confirm a policy is firing, discover a legacy path the set is not catching, and investigate a specific block. Forwarding the logs to a central analytics workspace turns per-sign-in records into trends you can alert on.

How do I manage Conditional Access policies as code?

Conditional Access policies are readable and writable through the Microsoft Graph API, which lets you export the policy set to a definition, store it in source control, review changes through the same pull-request process as other infrastructure, and reapply the definition to rebuild or replicate the posture. The repeatability benefit is real for disaster recovery, since a code-defined posture restores far more reliably than a hand-clicked one, but the larger benefit is reviewability: a diff shows exactly what an edit does to scope and controls, a reviewer can catch an overly broad exclusion before it ships, and the history records who changed what. Pair the code-defined posture with two recurring disciplines: scheduled review to confirm every exclusion still has a reason and that break-glass accounts remain excluded from blocking policies, and drift monitoring that compares the live set against the version-controlled definition so an out-of-band change surfaces as a difference rather than hiding. Confirm current Graph endpoints, scopes, and module versions against official documentation, since the surface changes.

Does Conditional Access replace role-based access control?

Conditional Access does not replace role-based access control; the two govern different dimensions and reinforce each other. Conditional Access governs the conditions of access: whether a valid credential, arriving in a given context, should proceed and what additional proof the context demands. Role-based and attribute-based access control govern the scope of access: once an identity is inside, what it is permitted to do and which resources it can touch. A design that hardens one while neglecting the other leaves a matching gap. Conditional Access can demand multifactor authentication and a managed device to reach a sensitive system, but if the identity then holds far more privilege than its job requires, a successful sign-in still over-exposes the tenant. Conversely, tight least-privilege roles do little if a stolen password reaches them without any conditional check. Strong posture pairs them: Conditional Access raises the bar for proving identity to sensitive systems, and least-privilege role assignment ensures even a fully proven identity touches only what its role requires.

Why do my Conditional Access changes sometimes take time to apply?

Conditional Access changes are not always instantaneous because the platform caches and propagates configuration, and existing sessions already granted under prior terms do not necessarily reevaluate the instant a policy changes. A new or edited policy applies to new sign-in evaluations as the change propagates, but a session that was granted before the change may continue under its original terms until it next reauthenticates, which is one reason sign-in frequency as a session control matters: it bounds how long a pre-change session can run before the new policy reaches it. This behavior has a practical implication for both testing and incident response. When you enable a policy, the absence of an immediate effect on a current session is expected rather than a failure, and when you tighten a policy in response to a concern, the tightening reaches active sessions on their next reauthentication rather than immediately. The exact propagation behavior and timing are platform details that change, so verify current behavior against the official documentation rather than assuming a fixed interval.