↳ GitHub sourceAnalytics ruleMedium
Anomalous sign-in location by user account and authenticating application
Description
'This query over Microsoft Entra ID sign-in considers all user sign-ins for each Microsoft Entra ID application and picks out the most anomalous change in location profile for a user within an individual application.
- Rule type
- Scheduled
- Version
- 2.0.5
- Declared status
- Available
- Query frequency
- 1d
- Query period
- 7d
- Trigger
- gt 0
Declared MITRE coverage
Declared sources
Metadata from the source file. No dependencies inferred from KQL.
Connectors
Data types
KQL query
Original query, unchanged.
// Adjust this figure to adjust how sensitive this detection is
let sensitivity = 2.5;
// Adjust this figure to set the value that defines the requested estimation accuracy. The default value is 1. Possible values are 0, 1, 2, 3, 4.
let dcountAccuracy = 1;
let AuthEvents = materialize(
union isfuzzy=True SigninLogs, AADNonInteractiveUserSignInLogs
| where TimeGenerated between (ago(7d) .. now())
| where ResultType == 0
| extend LocationDetails = LocationDetails_dynamic
| extend Location = strcat(LocationDetails.countryOrRegion, "-", LocationDetails.state,"-", LocationDetails.city)
| where Location != "--");
AuthEvents
| summarize dcount(Location, dcountAccuracy) by AppDisplayName, AppId, UserPrincipalName, UserId, bin(startofday(TimeGenerated), 1d)
| where dcount_Location > 2
| make-series CountOfLocations = sum(dcount_Location) on TimeGenerated step 1d by AppId, UserId
| extend (Anomalies, Score, Baseline) = series_decompose_anomalies(CountOfLocations, sensitivity, -1, 'linefit')
| mv-expand CountOfLocations to typeof(double), TimeGenerated to typeof(datetime), Anomalies to typeof(double), Score to typeof(double), Baseline to typeof(long)
| where Anomalies > 0 and Baseline > 0
| join kind=inner( AuthEvents | extend TimeStamp = startofday(TimeGenerated)) on UserId, AppId
| extend SignInDetails = bag_pack("TimeGenerated", TimeGenerated1, "Location", Location, "Source", IPAddress, "Device", DeviceDetail_dynamic)
| summarize SignInDetailsSet=make_set(SignInDetails, 1000) by UserId, UserPrincipalName, CountOfLocations, TimeGenerated, AppId, AppDisplayName
| extend Name = split(UserPrincipalName, "@")[0], UPNSuffix = split(UserPrincipalName, "@")[1]
Declared entities
Related content
Links established from declared identifiers and solution manifests.
Source provenance
GitHubDisplayed values come from files in Azure/Azure-Sentinel. They describe the published template, not your workspace configuration.
- File
- Solutions/Microsoft Entra ID/Analytic Rules/AnomalousUserAppSigninLocationIncrease-detection.yaml ↗
- Commit
9800e51↗- Source identifier
7cb8f77d-c52f-4e46-b82f-3cf2e106224a
GSTEP / CATALOG TRACKING
Added to catalog : 16 Sept 2026 · 05:49 UTC
Last change observed : 16 Sept 2026 · 05:49 UTC