Conditional Access (CA) in Entra ID is often called "the silver bullet" for identity security. In reality, it's a set of knobs that can be turned the wrong way - locking out legitimate users while still letting attackers slip through.

One thing to understand up front: Conditional Access never grants access. With no policies, a correct password is enough. Each policy only adds requirements (MFA, a compliant device) or blocks. So the gaps are almost always about what your policies don't cover.

Common Misconfigurations

Before Anything Else: Break-Glass Accounts

Create two cloud-only emergency access accounts with Global Administrator, long random credentials (ideally FIDO2 keys) stored securely offline, and exclude them from every Conditional Access policy. Alert on every sign-in to them. This is the safety net that lets you fix a mistake instead of opening a Microsoft support case while your whole tenant is locked out.

Every policy below excludes the break-glass accounts. Replace the placeholder object IDs with yours before you run anything.

Three Core Policies You Must Have

The examples use Microsoft Graph PowerShell and create every policy in report-only mode, so nothing is enforced until you've reviewed the impact.

# One-time setup Install-Module Microsoft.Graph.Identity.SignIns -Scope CurrentUser Connect-MgGraph -Scopes 'Policy.ReadWrite.ConditionalAccess','Policy.Read.All' # Your two emergency access accounts (object IDs) $breakGlass = @('00000000-0000-0000-0000-000000000001','00000000-0000-0000-0000-000000000002')

Policy 1 - MFA for Privileged Roles

$adminRoles = @( '62e90394-69f5-4237-9190-012177145e10' # Global Administrator 'e8611ab8-c189-46e8-94e1-60213ab1f814' # Privileged Role Administrator '7be44c8a-adaf-4e2a-84d6-ab2649e08a13' # Privileged Authentication Administrator '194ae4cb-b126-40b2-bd5b-6091b380977d' # Security Administrator 'b1be1c3e-b65d-4f19-8427-f6fa0d97feb9' # Conditional Access Administrator '29232cdf-9323-42fd-ade2-1d097af3e4de' # Exchange Administrator 'fe930be7-5e62-47db-91af-98c3a49a38b1' # User Administrator ) New-MgIdentityConditionalAccessPolicy -BodyParameter @{ displayName = 'CA01 - Require MFA for admin roles' state = 'enabledForReportingButNotEnforced' conditions = @{ users = @{ includeRoles = $adminRoles; excludeUsers = $breakGlass } applications = @{ includeApplications = @('All') } clientAppTypes = @('all') } grantControls = @{ operator = 'OR'; builtInControls = @('mfa') } }

Target directory roles, not just an "Admins" group - role-based targeting follows the permission, so a newly assigned Global Admin is covered automatically. Once this is working, go further: require MFA for all users, and require phishing-resistant MFA (an authentication strength) for admins.

Policy 2 - Block Legacy Authentication

New-MgIdentityConditionalAccessPolicy -BodyParameter @{ displayName = 'CA02 - Block legacy authentication' state = 'enabledForReportingButNotEnforced' conditions = @{ users = @{ includeUsers = @('All'); excludeUsers = $breakGlass } applications = @{ includeApplications = @('All') } clientAppTypes = @('exchangeActiveSync','other') } grantControls = @{ operator = 'OR'; builtInControls = @('block') } }

In Conditional Access, other covers the legacy protocols - IMAP, POP, SMTP AUTH, MAPI and older Office clients - and exchangeActiveSync covers basic-auth ActiveSync. These can't satisfy MFA, so blocking them closes a common bypass.

If something still depends on them - usually a scanner or line-of-business app sending mail - move it to OAuth or to an SMTP relay connector with its own restrictions. Don't reach for app passwords: they're a legacy per-user MFA feature, they don't work with Conditional Access MFA, and they're exactly the kind of long-lived secret you're trying to get rid of.

Policy 3 - Compliant Devices for Admin Portals

New-MgIdentityConditionalAccessPolicy -BodyParameter @{ displayName = 'CA03 - Admins require compliant device for Azure management' state = 'enabledForReportingButNotEnforced' conditions = @{ users = @{ includeRoles = $adminRoles; excludeUsers = $breakGlass } applications = @{ includeApplications = @('797f4846-ba00-4fd7-ba43-dac1f8f63013') } # Windows Azure Service Management API clientAppTypes = @('all') } grantControls = @{ operator = 'OR'; builtInControls = @('compliantDevice') } }

This forces admins managing Azure (portal, CLI, PowerShell) to be on a device that passes Intune compliance - encryption, supported OS, no jailbreak and so on. A stolen admin password used from an attacker's laptop fails here even if they also phish the MFA prompt. Consider adding the "Microsoft Admin Portals" app to the same policy to cover the Entra, Microsoft 365 and Exchange admin centers.

Testing Your Policies

Never roll out a new CA policy to "All users" without testing. Report-only mode evaluates the policy on every sign-in and records what it would have done, without enforcing it.

Give it a week, then check the sign-in logs (or the Conditional Access insights and reporting workbook) for results of Report-only: Failure. What you're looking for is legitimate sign-ins the policy would have blocked - the service account, the conference-room device, the one executive on an old mail client. Fix or deliberately exclude those, then turn the policy on:

$policy = Get-MgIdentityConditionalAccessPolicy -Filter "displayName eq 'CA02 - Block legacy authentication'" Update-MgIdentityConditionalAccessPolicy -ConditionalAccessPolicyId $policy.Id -State 'enabled'

Remediation Checklist

Final Thought

Conditional Access is a framework, not a single setting. Treat each policy as a rule in your security playbook: define the scope, enforce MFA or device compliance, test in report-only mode, then enable.

When done right, CA reduces the attack surface dramatically. When misconfigured, it gives you a false sense of security while attackers walk right through the back door.