Enriched Entra Sign In Logs Gsa Enforcement By Ca Policy
Query
// Global Secure Access Enforcement by Conditional Access Policy
// Hunting query which helps to identify and analyze sign-in requests outside of Global Secure Access
// with details about exclusion on Compliant Network conditions in Conditional Access
// Definition of Conditional Access Policy which blocks access outside of Compliant Network GSA
let CaPolicyGsaBlockOutside = '<DisplayNameOfConditionalAccessPolicyForBlockedOutsideOfGSA>';
// Definition of excluded Cloud Apps from compliant network CA, examples covers recommendation by Microsoft for exclusions
let ExplicitlyGsaExcludedCloudAppIds = dynamic([
"372140e0-b3b7-4226-8ef9-d57986796201", // Azure Windows VM Sign-In
"0000000a-0000-0000-c000-000000000000", // Microsoft Intune
"d4ebce55-015a-49b5-a083-c84d1797ae8c" // Microsoft Intune Enrollment
]);
union SigninLogs, AADNonInteractiveUserSignInLogs
// Filter for successful sign-ins to home tenant only
| where HomeTenantId == ResourceTenantId and ResultType == "0" // Successful sign-ins
// Filter for specific time window and user
// | where UserPrincipalName == "<UserPrincipalName>"
// and CreatedDateTime between ( todatetime('<StartTime>') .. todatetime('<EndTime>') )
// Expand device details
| extend DeviceDetail = iff(isempty( DeviceDetail_dynamic ), todynamic(DeviceDetail_string), DeviceDetail_dynamic)
| extend DeviceId = tostring(tolower(DeviceDetail.deviceId))
| extend DeviceName = tostring(toupper(DeviceDetail.displayName))
// Expand Token Protection Status details
| extend TokenProtectionStatus = iff(isempty( TokenProtectionStatusDetails_dynamic ), todynamic(TokenProtectionStatusDetails_string), TokenProtectionStatusDetails_dynamic)
| extend SignInSessionStatus = tostring(TokenProtectionStatus.signInSessionStatus)
// Correlate token acquisition with NetworkAccessTraffic logs from GSA
| join kind = leftouter ( NetworkAccessTraffic
| project TimeGenerated, TransactionId, ConnectionId, IPAddress = SourceIp, AgentVersion, UserId, DeviceId, UniqueTokenIdentifier = UniqueTokenId, InitiatingProcessName
) on UserId, DeviceId, UniqueTokenIdentifier, IPAddress
// Summarize Results
| extend ResultType = toint(ResultType)
| project-reorder CreatedDateTime, SessionId, IncomingTokenType, TokenIssuerType, SignInSessionStatus, UniqueTokenIdentifier, AppDisplayName, ResourceDisplayName, IsThroughGlobalSecureAccess, InitiatingProcessName
// Correlation with events from XDR AH EntraIdSignInEvents to get Conditional Access details
| join kind=innerunique (
EntraIdSignInEvents
| where IsGuestUser == "0" and ErrorCode == "0"
) on $left.SessionId == $right.SessionId, $left.CorrelationId == $right.CorrelationId, $left.OriginalRequestId == $right.RequestId, $left.ResultType == $right.ErrorCode, $left.IPAddress == $right.IPAddress, $left.UserId == $right.AccountObjectId
// Enrichment GSA Insights
| mv-apply ConditionalAccessPolicyGsa = parse_json(ConditionalAccessPolicies) to typeof(dynamic) on (
where ConditionalAccessPolicyGsa.displayName startswith (CaPolicyGsaBlockOutside)
)
| extend IsGsaEnforced = iff(
(
parse_json(ConditionalAccessPolicyGsa)["result"] == 'notApplied' and
parse_json(ConditionalAccessPolicyGsa)["excludeRulesSatisfied"] has 'locationId' and
parse_json(ConditionalAccessPolicyGsa)["enforcedGrantControls"][0] == 'Block'
), true, false)
| extend GsaEnforcedResourceScope = case(
(
(AppId in~ (ExplicitlyGsaExcludedCloudAppIds) or ResourceIdentity in~ (ExplicitlyGsaExcludedCloudAppIds)) and
parse_json(ConditionalAccessPolicyGsa)["excludeRulesSatisfied"] has 'appId')
, "ExplicitlyExcluded",
(parse_json(ConditionalAccessPolicyGsa)["includeRulesSatisfied"] has AppId)
, "ExplicitlyIncluded",
parse_json(ConditionalAccessPolicyGsa)["includeRulesSatisfied"] has 'allApps' and
parse_json(ConditionalAccessPolicyGsa)["excludeRulesSatisfied"] !has 'appId'
, "AllAppsIncluded",
(AppId !in~ (ExplicitlyGsaExcludedCloudAppIds) or ResourceIdentity !in~ (ExplicitlyGsaExcludedCloudAppIds)) and
parse_json(ConditionalAccessPolicyGsa)["excludeRulesSatisfied"] has 'appId'
, "MicrosoftExcluded", "Unknown"
)
| extend GsaEnforcedUserScope = case(
(
parse_json(ConditionalAccessPolicyGsa)["excludeRulesSatisfied"] has 'userId')
, "ExplicitlyExcluded",
(parse_json(ConditionalAccessPolicyGsa)["includeRulesSatisfied"] has 'userId')
, "ExplicitlyIncluded",
parse_json(ConditionalAccessPolicyGsa)["includeRulesSatisfied"] has 'allUsers' and
parse_json(ConditionalAccessPolicyGsa)["excludeRulesSatisfied"] !has 'userId'
, "AllUsersIncluded",
parse_json(ConditionalAccessPolicyGsa)["includeRulesSatisfied"] !has 'allUsers' and
(parse_json(ConditionalAccessPolicyGsa)["includeRulesSatisfied"] !has 'userId') and
parse_json(ConditionalAccessPolicyGsa)["excludeRulesSatisfied"] !has 'userId'
, "UserNotIncluded", "Unknown"
)
| project CreatedDateTime, UserPrincipalName, IncomingTokenType, SignInSessionStatus, AppDisplayName, ResourceDisplayName, InitiatingProcessName, IsThroughGlobalSecureAccess, ConnectionId, IsGsaEnforced, GsaEnforcedUserScope, GsaEnforcedResourceScope, ConditionalAccessPolicyGsa
| sort by CreatedDateTime desc
// Filter for sign-ins which are not going trough GSA and have not been enforced to use GSA
| where IsThroughGlobalSecureAccess == false and IsGsaEnforced == falseExplanation
This KQL (Kusto Query Language) script is designed to analyze and identify sign-in requests that occur outside of a secure network environment, specifically focusing on Microsoft's Global Secure Access (GSA) and Conditional Access policies. Here's a simplified breakdown:
-
Purpose: The query aims to find and analyze successful sign-in attempts that bypass the Global Secure Access (GSA) network, which should typically be blocked by a specific Conditional Access policy.
-
Definitions:
- CaPolicyGsaBlockOutside: This is a placeholder for the name of the Conditional Access policy that blocks access outside the GSA network.
- ExplicitlyGsaExcludedCloudAppIds: A list of cloud applications that are explicitly excluded from the GSA network requirement, based on Microsoft's recommendations.
-
Data Sources: The query pulls data from sign-in logs and non-interactive user sign-in logs, as well as network access traffic logs.
-
Filtering:
- It filters for successful sign-ins within the user's home tenant.
- It expands details about the device and token protection status involved in the sign-ins.
- It correlates sign-in data with network access logs to identify if the sign-in went through the GSA.
-
Conditional Access Policy Analysis:
- The query checks if the Conditional Access policy was applied and whether any exclusion rules were satisfied.
- It determines if the sign-in was enforced to use GSA and categorizes the enforcement scope for both resources and users (e.g., explicitly included, excluded, or all included).
-
Output:
- The results are sorted by the time of sign-in and include details such as user information, application names, and whether the sign-in was through GSA.
- It specifically highlights sign-ins that did not go through GSA and were not enforced to use GSA, which could indicate a policy gap or potential security issue.
In summary, this query helps security analysts identify and investigate sign-ins that occur outside of the intended secure network environment, ensuring that Conditional Access policies are effectively enforced.
Details

Thomas Naunheim
Released: November 8, 2025
Tables
Keywords
Operators