To find out why a Conditional Access policy did or did not apply, open the user's sign-in event in Entra ID > Monitoring & health > Sign-in logs, check the Conditional Access and Report-only tabs, and open the policy details to see which collected sign-in property failed to match a condition. Then reproduce the same sign-in with the What If tool (or the Graph evaluate API), which lists every policy that would apply and, for each policy that wouldn't, the first condition that wasn't satisfied. A policy applies only when all of its configured conditions are satisfied, so the answer is almost always one specific condition.
Who this is for and what you will have at the end
This guide is for administrators and help desk engineers who need to explain a Conditional Access outcome: a user who was blocked unexpectedly, a user who should have been prompted for MFA but wasn't, or a report-only policy whose impact you want to understand before enforcing it. It assumes Conditional Access is already in use in the tenant.
At the end you will have:
- A repeatable way to locate the exact sign-in event and read its Conditional Access result.
- A What If simulation that confirms the cause and tests a fix before you change a policy.
- A Microsoft Graph PowerShell script and KQL queries to answer the same question for many users or sign-ins.
- A list of the common reasons a policy applies or doesn't, and the error codes users report.
How Conditional Access decides whether a policy applies
Every policy has assignments (users, agents or workload identities, and target resources) and conditions (device platforms, client apps, locations, risk levels, filters and so on). For a given sign-in, a policy applies only when every configured assignment and condition is satisfied. Conditions you didn't configure are ignored. If one configured condition doesn't match, the policy isn't applied, and its grant and session controls are never evaluated.
That gives two different questions to answer:
- Did the policy apply? That depends only on assignments and conditions.
- If it applied, were its controls satisfied? That is where MFA, compliant device, block and session controls come in.
Two behaviors cause most of the confusion:
- Service dependencies. Some apps call other resources during sign-in. A user who thinks they are signing in to the Azure portal is also requesting a token for Azure Resource Manager, and a policy on that resource applies. The sign-in log shows the application and the resource separately.
- Audience. A sign-in to an app like Microsoft Teams requests access to several resources at once, such as chat, calendar and files. The sign-in log lists them as Audience under the resource section of each policy, and a policy can apply because one of those audiences is in scope.
Prerequisites
| Task | Minimum access |
|---|---|
| Open sign-in logs in the admin center | Reports Reader |
| See which Conditional Access policies applied to a sign-in | Global Reader, Security Reader, Security Administrator or Conditional Access Administrator |
| Read sign-ins with Microsoft Graph | AuditLog.Read.All, plus Policy.Read.ConditionalAccess (or Policy.Read.All) to receive the applied policies |
| Run the What If evaluation with Microsoft Graph | Policy.Read.ConditionalAccess |
| Use the sign-in diagnostic from the sign-in logs | Reports Reader, plus Billing Administrator as documented for the diagnostic |
| Use the Conditional Access insights and reporting workbook | Security Reader plus access to a Log Analytics workspace receiving sign-in logs (Microsoft documents Log Analytics workspace Contributor), and Microsoft Entra ID P1 |
If a user or app can read sign-in logs but not Conditional Access data, Microsoft Graph omits the appliedConditionalAccessPolicies property from the response instead of returning an error. If your script shows empty policy lists, check permissions first.
For PowerShell, install the Microsoft Graph PowerShell SDK modules Microsoft.Graph.Reports and Microsoft.Graph.Identity.SignIns.
Step 1: Collect the facts from the failed sign-in
Ask the user for the error page. In a browser, the Conditional Access interrupt page usually explains the problem, and selecting More Details shows troubleshooting information. Record:
- Correlation ID and Request ID
- Timestamp (and the user's time zone)
- The app the user was opening, and the device and browser used
The correlation ID groups sign-ins from the same session, and the request ID identifies the issued token. Microsoft support asks for the request ID, time and date if you open a case.
Step 2: Find the sign-in event
- Sign in to the Microsoft Entra admin center as at least a Reports Reader.
- Browse to Entra ID > Monitoring & health > Sign-in logs.
- Add filters to narrow the list: Correlation ID when you have one, Username, Date, Resource, and Conditional Access (scope it to failures to cut the noise).
Check the right tab. Sign-ins are split into interactive user sign-ins, non-interactive user sign-ins, service principal sign-ins and managed identity sign-ins. A client that uses a token or code on the user's behalf, without the user entering a factor, is logged as non-interactive, and a single authentication can produce several sign-in requests that appear on either tab.
Keep in mind that the times shown are in the time zone of the administrator viewing the log, not the user.
Step 3: Read the Conditional Access tab
Open the event and select the Conditional Access tab. Every policy that could apply to the sign-in is listed with its result:
| Result | Meaning |
|---|---|
| Success | The policy applied and its requirements were met |
| Failure | The policy applied and its grant controls weren't satisfied or are set to block |
| Not applied | The sign-in didn't match the policy's criteria |
| Disabled | The policy was disabled at the time of the sign-in |
The overall Conditional Access status on the event works a little differently. Success means one or more policies applied to or were evaluated for the user and application, even if other conditions later excluded them. Failure means at least one policy matched the user and application and its grant controls weren't satisfied or blocked access.
Find the condition that didn't match
Select the ellipsis next to a policy to open its details. The left side shows the properties collected at sign-in (user, application, client app, device platform, location, risk, device state). The right side shows whether each one satisfied the policy's conditions. This is usually enough to see the cause, for example a device platform reported as macOS when the policy targets only Windows.
Also review:
- Basic info for the application, resource, client app and error code.
- Device info for the browser and operating system, and whether the device was reported as compliant, managed or Microsoft Entra hybrid joined.
- Location for the IP address. IP-to-location mapping is best effort, and VPN or mobile providers can place users far from where they are.
- Authentication Details for the sequence of methods and whether MFA was satisfied by a claim in the token. This tab can show incomplete data until aggregation finishes.
Expected Not applied results
Some sign-ins show Not applied by design. Bootstrap scenarios that would create a circular dependency, such as device registration, device compliance checks and Network Policy Server connectors, are exempt. Windows Hello for Business sign-ins also show Not applied, because Conditional Access protects access to cloud resources, not the Windows sign-in itself.
Step 4: Check the Report-only tab
Policies in report-only mode are evaluated but not enforced, and their results appear on the Report-only tab:
| Result | Meaning |
|---|---|
| Report-only: Success | Conditions, non-interactive grant controls and session controls were satisfied |
| Report-only: Failure | Conditions were satisfied but a non-interactive control wasn't, for example a block control or a non-compliant device |
| Report-only: User action required | Conditions were satisfied, but the user would have had to act (MFA, terms of use); the user isn't prompted |
| Report-only: Not applied | Not all configured conditions were satisfied |
Report-only mode doesn't cover policies scoped to User Actions. One caution: report-only policies that require a compliant device can prompt users on macOS, iOS and Android to select a device certificate, even though nothing is enforced. Microsoft recommends excluding those platforms from report-only device compliance policies.
For a quick aggregate view, the policy impact view lets a Security Reader see the potential impact of a policy on interactive sign-ins over the past 24 hours, 7 days or 1 month.
Step 5: Reproduce the sign-in with the What If tool
The sign-in log tells you what happened. The What If tool tells you what would happen for a set of inputs, which is how you confirm the cause and test a fix.
- Browse to Entra ID > Conditional Access > Policies and select What If on the toolbar.
- Enter the required conditions: the identity (a user, an agent identity (preview), or a single-tenant service principal), the target resource (cloud app, user action or authentication context), the device platform and the client app.
- Copy the remaining values from the sign-in event: IP address or country, sign-in risk, user risk, device state. Optional conditions you leave empty are treated as none.
- Select What If.
The report shows whether classic policies exist in the tenant, the policies that would apply (with the grant and session controls that must be satisfied), and the policies that wouldn't apply. For each policy that doesn't apply, the reason shown is the first condition that wasn't satisfied. If you fix that condition, run the evaluation again, because a second condition might also fail. Has filter indicates that the policy uses app filters based on custom security attributes.
Only enabled and report-only policies are evaluated.
Know the What If limits
- It doesn't evaluate service dependencies. A What If for Teams doesn't show a policy on Office 365 Exchange Online.
- The evaluation engine expects all sign-in parameters. If a policy has a location or risk condition and you don't supply that value, the condition can't be evaluated and the policy is reported as not applying. Microsoft's own example shows a policy with location and sign-in risk conditions that only reports as applying once both values are supplied.
- Specify applications by App ID. Groups of apps such as Office 365 or Microsoft Admin Portals don't result in a match in the evaluation API. You can copy the application ID from the Basic info tab of the sign-in event.
Step 6: Script the evaluation with Microsoft Graph
The portal tool calls the Microsoft Graph What If evaluation API, POST /identity/conditionalAccess/evaluate. Scripting it is useful when you need to test the same scenario for many users or keep a record of results before and after a policy change.
Connect-MgGraph -Scopes "Policy.Read.ConditionalAccess"
Import-Module Microsoft.Graph.Identity.SignIns
$params = @{
signInIdentity = @{
"@odata.type" = "#microsoft.graph.userSignIn"
userId = "<user-object-id>"
}
signInContext = @{
"@odata.type" = "#microsoft.graph.applicationContext"
includeApplications = @("<application-id>")
}
signInConditions = @{
devicePlatform = "windows"
clientAppType = "browser"
country = "US"
ipAddress = "<public-ip-from-the-sign-in>"
signInRiskLevel = "none"
userRiskLevel = "none"
deviceInfo = @{ isCompliant = $false }
}
appliedPoliciesOnly = $false
}
Test-MgIdentityConditionalAccess -BodyParameter $params | Format-ListSet appliedPoliciesOnly to $true to return only the policies that would apply. With $false, each returned policy includes policyApplies and, when it's false, an analysisReasons value:
| analysisReasons value | What to check |
|---|---|
users | Include and exclude users, groups and roles |
application | Target resources and exclusions; supply an App ID |
devicePlatform | Platform conditions |
clientApps | Client app types (browser, mobile and desktop, Exchange ActiveSync, other) |
location | Named locations and the IP address or country you supplied |
signInRisk, userRisk, insiderRisk | Risk level conditions |
devices | Device filter or device state |
authenticationFlow | Device code flow or authentication transfer conditions |
notEnoughInformation | A condition needs a value you didn't supply |
policyNotEnabled | The policy is off |
Other documented values include workloadIdentities, userActions, authenticationContext, time, emptyPolicy, invalidPolicy and invalidCondition. Supported clientAppType values are all, browser, mobileAppsAndDesktopClients, exchangeActiveSync, easSupported and other, and devicePlatform accepts android, iOS, windows, windowsPhone, macOS, linux and all.
To pull the real sign-in for comparison, query the sign-in logs for a time window and filter locally on the correlation ID:
Connect-MgGraph -Scopes "AuditLog.Read.All", "Policy.Read.ConditionalAccess"
Import-Module Microsoft.Graph.Reports
$signIn = Get-MgAuditLogSignIn -All -Filter "createdDateTime ge 2026-10-10T08:00:00Z and createdDateTime le 2026-10-10T09:00:00Z" |
Where-Object CorrelationId -eq "<correlation-id>"
$signIn.AppliedConditionalAccessPolicies | Format-Table DisplayName, ResultAlways filter by a time range; Microsoft recommends it to avoid request time-outs on this endpoint. Keep the window short: the API returns at most 1,000 sign-ins per page, most recent first, and -All follows the paging links so the correlation ID isn't missed on a later page. The v1.0 endpoint returns interactive sign-ins; look in the portal's non-interactive tab or Log Analytics (below) for non-interactive events.
Step 7: Query results at scale in Log Analytics
If your sign-in logs are sent to a Log Analytics workspace, KQL answers questions like "which policies blocked this user this week" or "how many sign-ins would this report-only policy have interrupted". In the SigninLogs table, ConditionalAccessPolicies is a dynamic column, so expand it into one row per policy:
SigninLogs
| where TimeGenerated > ago(7d)
| where UserPrincipalName == "adele@contoso.com"
| mv-expand CAPolicy = ConditionalAccessPolicies
| extend PolicyName = tostring(CAPolicy.displayName), PolicyResult = tostring(CAPolicy.result)
| project TimeGenerated, CorrelationId, AppDisplayName, ResourceDisplayName, ClientAppUsed, ConditionalAccessStatus, PolicyName, PolicyResult
| order by TimeGenerated descTo estimate the impact of report-only policies, count distinct sign-ins rather than expanded rows, because each sign-in appears once per policy after mv-expand:
SigninLogs
| where TimeGenerated > ago(7d)
| mv-expand CAPolicy = ConditionalAccessPolicies
| extend PolicyName = tostring(CAPolicy.displayName), PolicyResult = tostring(CAPolicy.result)
| where PolicyResult in ("reportOnlyFailure", "reportOnlyInterrupted")
| summarize SignIns = dcount(CorrelationId), Users = dcount(UserPrincipalName) by PolicyName, PolicyResult
| order by SignIns descNon-interactive sign-ins live in AADNonInteractiveUserSignInLogs, where ConditionalAccessPolicies is stored as a string. Convert it first:
AADNonInteractiveUserSignInLogs
| where TimeGenerated > ago(1d)
| where UserPrincipalName == "adele@contoso.com"
| mv-expand CAPolicy = todynamic(ConditionalAccessPolicies)
| extend PolicyName = tostring(CAPolicy.displayName), PolicyResult = tostring(CAPolicy.result)
| where PolicyResult == "failure"
| project TimeGenerated, AppDisplayName, ResourceDisplayName, PolicyName, PolicyResultPossible result values include success, failure, notApplied, notEnabled, reportOnlySuccess, reportOnlyFailure, reportOnlyNotApplied and reportOnlyInterrupted. In Microsoft Graph, the report-only values are returned only when you send the Prefer: include-unknown-enum-members header.
The Conditional Access insights and reporting workbook (Entra ID > Conditional Access > Insights and reporting) shows the same data as Success, Failure, User action required and Not applied tiles, with breakdowns by device state, platform, client app, location, application and sign-in risk. If you download sign-in logs to analyze offline, choose JSON format to keep the report-only results.
Common reasons a policy did or didn't apply
| Symptom | Likely cause | Where to confirm |
|---|---|---|
| Policy shows Not applied for a user who should be in scope | User is in an excluded group or role, or the included group isn't the one you think | Policy details in the sign-in event; What If reason users |
| MFA policy didn't prompt | Requirement already satisfied by an MFA claim in the token | Authentication Details tab |
| Block policy applied to an app you didn't target | Service dependency or one of the audiences is in scope | Resource and Audience in the policy details |
| Compliant device policy fails for a user who has a compliant device | The sign-in didn't report the device as compliant or managed | Device info tab for that specific sign-in |
| Location policy behaves unexpectedly | IP address resolves to a different place, or isn't in the named location | Location tab; What If with the exact IP address |
| What If says a policy doesn't apply but it does in real sign-ins | Missing input values or an app group used instead of App ID | Rerun What If with all conditions and the App ID |
| Legacy client blocked or not blocked | Client app type is Exchange ActiveSync or other clients | Client app on Basic info |
Troubleshooting common error codes
Users usually report the error code from the browser. Each appears with the AADSTS prefix.
| Error code | Error string | Typical fix |
|---|---|---|
AADSTS53000 | DeviceNotCompliant | Bring the device into compliance in Intune, then sign in again |
AADSTS53001 | DeviceNotDomainJoined | Use a Microsoft Entra hybrid joined device or adjust the policy scope |
AADSTS53002 | ApplicationUsedIsNotAnApprovedApp | Use a client app that the policy accepts as approved |
AADSTS53003 | BlockedByConditionalAccess | Find the blocking policy on the Conditional Access tab |
AADSTS53004 | ProofUpBlockedDueToRisk | Registration was blocked because of risk; investigate and remediate the risk first |
AADSTS53009 | Application needs to enforce Intune protection policies | Use an app that supports Intune app protection policies |
If the event details still don't explain the outcome, launch the sign-in diagnostic from the Basic info tab (Troubleshoot Event). It can also detect sign-ins that weren't interrupted but should have been.
If an incorrect policy locked out every administrator, an unaffected admin can disable it; if none exist, open a Microsoft support request. Microsoft specifically warns against assigning a block, compliant device, hybrid join or app protection requirement to all users and all resources, because each can lock out the whole organization, administrators included. For how Conditional Access fits into a wider access model, see the Zero Trust remote access architecture.
Checklist
- Correlation ID, request ID, timestamp and app collected from the user.
- Sign-in event found on the correct tab (interactive or non-interactive).
- Conditional Access and Report-only tabs reviewed; policy details opened for the policy in question.
- Service dependencies and audiences checked for unexpected policies.
- What If run with every condition supplied, the App ID and the user's real IP address.
- Fix tested in What If (or a report-only copy of the policy) before changing the enforced policy.
- KQL or Graph query saved for repeat investigations.
References
- The Conditional Access What If tool
- Troubleshooting sign-in problems with Conditional Access
- Conditional Access report-only mode and policy impact
- Conditional Access insights and reporting workbook
- Learn about the sign-in log activity details
- How to use Microsoft Entra Sign-in diagnostics
- What If evaluation (Microsoft Graph)
- whatIfAnalysisResult resource type
- signInConditions resource type
- appliedConditionalAccessPolicy resource type
- List signIns (Microsoft Graph)
- SigninLogs table reference
- AADNonInteractiveUserSignInLogs table reference