Agent Foskett Academy • KQL Academy • Module 11 • Lesson 134

Lesson 134 — The Conditional Access Result Didn't Tell the Whole Story

The sign-in record said Conditional Access: success.

That sounds reassuring. But what exactly succeeded? Which policies were evaluated? Which ones were not applied? Was another policy in report-only mode showing that the same sign-in would have failed under a future control?

In this lesson, we investigate Conditional Access as evidence rather than treating one status field as the conclusion. We will use SigninLogs, expand ConditionalAccessPolicies, inspect policy-level results and place the outcome back into the full identity timeline.

A green Conditional Access result answers one question. An investigator still has several more to ask.
Agent Foskett KQL Academy Conditional Access investigation lesson
What you will investigate

A suspicious Microsoft Entra sign-in whose top-level Conditional Access result appears reassuring.

✓ Interpret ConditionalAccessStatus
✓ Expand individual policy results
✓ Investigate report-only outcomes
✓ Correlate CA with the full sign-in

The investigation begins

01:47 UTC ↓ Unfamiliar sign-in ↓ New source IP ↓ Conditional Access status: SUCCESS ↓ The analyst almost closes the investigation ↓ Then the individual policies are expanded ↓ Some policies succeeded ↓ Some were not applied ↓ A report-only policy shows a different outcome ↓ QUESTION What did Conditional Access actually prove about this sign-in?

Learning objectives

Interpret top-level Conditional Access status, inspect individual policies evaluated during a sign-in, identify report-only outcomes and combine Conditional Access evidence with authentication, application, device, IP and location context.

Why this is different from a CA fundamentals lesson

This is not about designing Conditional Access policies. It is about investigating the evidence left behind when those policies evaluate a real sign-in.

Step 1 — start with the complete sign-in

Begin with the event itself. Conditional Access is one part of the sign-in, so keep the user, application, resource, source and authentication result beside it.

review-conditional-access-signin.kql
123456789101112131415
let TargetUser = "alex.wilson@contoso.com";
SigninLogs
| where TimeGenerated > ago(24h)
| where UserPrincipalName =~ TargetUser
| project TimeGenerated,
          UserPrincipalName,
          AppDisplayName,
          ResourceDisplayName,
          IPAddress,
          Location,
          ResultType,
          ResultDescription,
          ConditionalAccessStatus,
          AuthenticationRequirement
| order by TimeGenerated desc

What does success mean?

At the top level, ConditionalAccessStatus records the status of Conditional Access for the sign-in. A success tells us that the activated Conditional Access requirements relevant to that evaluation were satisfied. It does not mean the sign-in is automatically benign.

What does notApplied mean?

A notApplied result means Conditional Access was not applied to that sign-in. The next investigative question is why: scope, conditions, exclusions, application context or another aspect of the request may explain it.

Step 2 — understand the distribution

Before focusing on one incident, see how Conditional Access statuses appear across the environment.

summarize-conditional-access-status.kql
12345
SigninLogs
| where TimeGenerated > ago(7d)
| summarize SignInCount=count()
          by ConditionalAccessStatus
| order by SignInCount desc

Baselines matter here too

If most interactive sign-ins for a population normally show Conditional Access success, an unexpected notApplied pattern may deserve investigation. The value comes from comparing the event with expected policy behaviour.

Do not confuse CA failure with every sign-in failure

A sign-in can fail for reasons unrelated to Conditional Access. Keep ResultType and ResultDescription beside the Conditional Access fields so you do not collapse different failure causes into one story.

Step 3 — expand the individual policies

The top-level status is only the summary. ConditionalAccessPolicies contains the policies triggered by the sign-in. Expand the dynamic field so each policy can be examined separately.

expand-conditional-access-policies.kql
123456789101112131415
let TargetUser = "alex.wilson@contoso.com";
SigninLogs
| where TimeGenerated > ago(24h)
| where UserPrincipalName =~ TargetUser
| where ConditionalAccessPolicies != "[]"
| mv-expand Policy = ConditionalAccessPolicies
| extend PolicyName = tostring(Policy.displayName),
         PolicyResult = tostring(Policy.result)
| project TimeGenerated,
          AppDisplayName,
          IPAddress,
          ConditionalAccessStatus,
          PolicyName,
          PolicyResult
| order by TimeGenerated desc

One sign-in, several policy outcomes

A single sign-in can have multiple Conditional Access policies associated with it. Looking only at the top-level result can hide the fact that different policies produced different outcomes.

Policy names provide context

Once expanded, the policy display name can help the analyst understand what control was being evaluated. Do not infer the entire policy configuration from its name alone; use the name as a pivot into the actual policy when required.

Step 4 — inspect grant and session controls

Policy-level data can also expose enforced grant and session controls. These fields help explain what the policy expected from the sign-in.

inspect-ca-policy-controls.kql
12345678910111213141516
let TargetUser = "alex.wilson@contoso.com";
SigninLogs
| where TimeGenerated > ago(24h)
| where UserPrincipalName =~ TargetUser
| where ConditionalAccessPolicies != "[]"
| mv-expand Policy = ConditionalAccessPolicies
| extend PolicyName = tostring(Policy.displayName),
         PolicyResult = tostring(Policy.result),
         GrantControls = tostring(Policy.enforcedGrantControls),
         SessionControls = tostring(Policy.enforcedSessionControls)
| project TimeGenerated,
          PolicyName,
          PolicyResult,
          GrantControls,
          SessionControls
| order by TimeGenerated desc

The result needs the requirement

Knowing that a policy succeeded is more useful when you also understand what control it enforced. The investigative question becomes: what requirement was satisfied, and how?

AuthenticationRequirement adds another clue

AuthenticationRequirement records the highest authentication level needed through the sign-in steps. AuthenticationRequirementPolicies can identify sources of that requirement, including Conditional Access and other mechanisms.

Step 5 — hunt report-only results

Report-only policies are evaluated during sign-in but are not enforced. Their results can therefore tell an investigator what a proposed policy would have done without implying that it actually blocked or challenged the user.

hunt-report-only-ca-results.kql
1234567891011121314
SigninLogs
| where TimeGenerated > ago(7d)
| where ConditionalAccessPolicies != "[]"
| mv-expand Policy = ConditionalAccessPolicies
| extend PolicyName = tostring(Policy.displayName),
         PolicyResult = tostring(Policy.result)
| where PolicyResult in (
    "reportOnlySuccess",
    "reportOnlyFailure",
    "reportOnlyNotApplied"
)
| summarize SignInCount=count()
          by PolicyName, PolicyResult
| order by SignInCount desc

Why report-only is valuable evidence

Suppose the enforced policies allow the sign-in, but a report-only policy returns reportOnlyFailure. That does not mean the user was blocked. It tells you that the proposed policy would have produced a different decision under its configured conditions.

Do not rewrite history

An investigator must distinguish what was enforced from what would have happened. Report-only results are excellent context, but they must never be described as controls that actually stopped the sign-in.

Step 6 — put Conditional Access back into the timeline

Finish by rebuilding the sign-in with the fields needed to test the whole story. Conditional Access should now sit beside authentication, application, resource, source, client and device evidence.

build-ca-investigation-timeline.kql
12345678910111213141516171819
let TargetUser = "alex.wilson@contoso.com";
SigninLogs
| where TimeGenerated > ago(24h)
| where UserPrincipalName =~ TargetUser
| project TimeGenerated,
          ResultType,
          ResultDescription,
          ConditionalAccessStatus,
          AuthenticationRequirement,
          AuthenticationRequirementPolicies,
          AppDisplayName,
          ResourceDisplayName,
          IPAddress,
          Location,
          ClientAppUsed,
          IsInteractive,
          DeviceDetail,
          CorrelationId
| order by TimeGenerated asc

A successful policy does not validate the source

A policy can work exactly as designed while the session still deserves investigation. An unfamiliar IP, unusual device, unexpected resource or suspicious sequence before and after authentication may still matter.

A failed policy is not automatically an attack

Users can legitimately fail Conditional Access requirements because a device is unmanaged, an authentication strength is not satisfied, a location is outside policy conditions or another control blocks access. The failure is evidence, not a verdict.

Evidence table

ObservationWhat it supportsWhat it does not prove
ConditionalAccessStatus = successRelevant activated CA requirements were satisfied for the evaluation.That the person behind the session was legitimate.
ConditionalAccessStatus = failureConditional Access prevented the sign-in from satisfying required access controls.That the attempt was malicious.
ConditionalAccessStatus = notAppliedConditional Access was not applied to the sign-in.Why it was not applied without policy context.
Policy result = reportOnlyFailureA report-only policy would have failed under that evaluation.That the sign-in was actually blocked.
Several policies show different resultsThe sign-in was evaluated against multiple policy contexts.That the top-level status explains every policy decision.
CA success plus unusual source/deviceThe access control succeeded but other identity evidence remains unusual.That the investigation can be closed.

Agent Foskett's investigation

01:47 Successful sign-in ↓ Source IP is unfamiliar ↓ Conditional Access says SUCCESS ↓ Temptation: "The controls worked, so it must be okay" ↓ KQL expands ConditionalAccessPolicies ↓ Individual policies are reviewed ↓ A report-only policy shows reportOnlyFailure ↓ AuthenticationRequirement is checked ↓ Device and application context are compared ↓ The sign-in is placed beside the user's normal history ↓ Conditional Access did its job ↓ But it never answered the identity question ↓ The investigation continues
Security controls can tell you whether their conditions were satisfied. They cannot always tell you who was sitting behind the keyboard.

Investigation questions to ask next

  • Which Conditional Access policies were actually evaluated?
  • Which policies succeeded, failed, were not applied or were report-only?
  • What grant or session controls did the relevant policy require?
  • Was MFA or another authentication strength required?
  • Did the sign-in originate from a normal IP, location and device?
  • Was the application or resource normal for this user?
  • Did a report-only policy identify a gap in the currently enforced controls?
  • Were there policy changes shortly before the sign-in?
  • What happened in the account immediately after successful access?

Lesson 134 key takeaways

  • Conditional Access is evidence inside the sign-in, not the whole investigation.
  • ConditionalAccessStatus provides a useful top-level result.
  • ConditionalAccessPolicies lets analysts inspect policy-level outcomes.
  • A successful Conditional Access result does not prove the session is benign.
  • A failed Conditional Access result does not prove malicious intent.
  • notApplied requires policy and sign-in context.
  • Report-only policies are evaluated but not enforced.
  • Keep enforced outcomes separate from report-only outcomes in your conclusions.
  • Authentication, device, IP, location, application and resource context still matter.
  • The investigator's job is to explain the complete sequence, not stop at a green status.

Continue your KQL investigation training

Lesson 134 continues Module 11: Identity Threat Hunting. Next we investigate privileged role activation and why timing can turn an administrative action into a critical clue.

Related Agent Foskett Investigations

Continue beyond the policy result. These identity investigations reinforce the same principle: a control outcome is one clue in a wider evidence chain.

🔎 KQL Academy — Module 11: Identity Threat Hunting

Use KQL to investigate identity behaviour as evidence.

Investigate Conditional Access results with KQL

Lesson 134 of the Agent Foskett KQL Academy teaches analysts how to investigate Microsoft Entra Conditional Access using SigninLogs, ConditionalAccessStatus, ConditionalAccessPolicies, policy-level outcomes, report-only results and full sign-in context.

Conditional Access evidence in Microsoft Entra sign-in investigations

A Conditional Access success, failure or notApplied result is useful evidence, but analysts should inspect the individual policies and correlate the outcome with authentication, device, source, application and resource activity before reaching a conclusion.