A hardened Entra tenant still needs centralized visibility. Local retention limits and weak correlation leave long-lived identity attacks undetected.
Preface
Identity telemetry must be centralized, hunted, and acted on quickly. Local Entra logs alone are not enough against sophisticated operators.
Entra ID keeps sign-in and audit logs for a limited period (30 days with a P1 or P2 license, less without one), and the portal is built for looking at one event at a time. Identity attacks are rarely one event. They are a sequence: reconnaissance, a password spray or token theft, a successful sign-in, then persistence through new credentials, consent grants or role assignments. Seeing that sequence requires the logs in one place, kept long enough, and queried by people who know what they are looking for.
Problem
Without SIEM correlation, teams may miss sequences such as password spray success followed by new application credential registration. That gap enables persistence and quiet exfiltration.
Each step on its own looks routine. Failed sign-ins happen all day. Admins add secrets to applications every week. The signal is in the combination: the same account, a short time window, an unusual source. Without correlation, each event is closed as noise, and by the time anyone looks closely the activity has aged out of the portal's retention.
Solution
Align with NIST SP 800-86 and build a Sentinel hunting framework:
- Stream SigninLogs, AuditLogs, and AADNonInteractiveUserSignInLogs into Sentinel.
- Build KQL detections for anomalous admin actions, credential additions, and proxy-routed sign-ins.
- Automate response playbooks to disable accounts or revoke sessions on high-severity alerts.
Data Collection Design
Use the Microsoft Entra ID data connector and enable, at minimum:
| Table | Why it matters |
|---|---|
| SigninLogs | Interactive user sign-ins, Conditional Access results, risk details |
| AADNonInteractiveUserSignInLogs | Token refreshes and client sign-ins, where token replay often shows |
| AADServicePrincipalSignInLogs | Application and service principal authentication |
| AADManagedIdentitySignInLogs | Managed identity token requests |
| AuditLogs | Directory changes: roles, apps, credentials, consent, policies |
| AADUserRiskEvents, AADRiskyUsers | Entra ID Protection detections |
Non-interactive and service principal sign-ins are high-volume, and teams often skip them to save cost. They are also where many identity attacks are visible. If cost is a constraint, consider lower-cost log tiers for long retention and keep analytics-tier retention long enough to cover your typical investigation window. Microsoft Graph activity logs are a valuable addition when you need to see what an identity did with its token, not only that it signed in.
Building a Hunting Practice
Start with hypotheses
Effective hunting starts from a specific question: "Has any account that failed sign-ins from a spray source later succeeded and changed an application?" Map hypotheses to MITRE ATT&CK techniques such as T1110.003 (Password Spraying) and T1098.001 (Additional Cloud Credentials) so coverage gaps are visible.
Promote what works
A hunting query that finds something real, or that runs cleanly for several weeks, should become a scheduled analytics rule with entity mapping, so incidents link accounts, IP addresses and applications automatically. Use bookmarks in Sentinel to preserve evidence found during a hunt.
Use context
Watchlists of break-glass accounts, privileged users, known partner IP ranges and sanctioned applications reduce false positives and make alerts on the important objects stand out.
KQL: Unauthorized Application Credential Additions
AuditLogs
| where OperationName in ("Add owner to application",
"Add service principal credentials",
"Update application – Certificates and secrets management")
| extend TargetApp = tostring(TargetResources[0].displayName)
| extend Actor = coalesce(tostring(InitiatedBy.user.userPrincipalName),
tostring(InitiatedBy.app.displayName))
| project TimeGenerated, OperationName, TargetApp, Actor, Result, ResultReason
Audit operation names must match exactly, which is why the list uses in with the full names rather than partial matches.
KQL: Spray Success Followed by Credential Changes
let window = 1d;
let spraySources = SigninLogs
| where TimeGenerated > ago(window) and ResultType == "50126"
| summarize FailedAccounts = dcount(UserPrincipalName) by IPAddress
| where FailedAccounts >= 10;
let compromised = SigninLogs
| where TimeGenerated > ago(window) and ResultType == "0"
| join kind=inner spraySources on IPAddress
| project SuccessTime = TimeGenerated, UserPrincipalName, IPAddress;
AuditLogs
| where TimeGenerated > ago(window)
| where OperationName in ("Add service principal credentials",
"Update application – Certificates and secrets management",
"Add member to role", "Consent to application")
| extend UserPrincipalName = tostring(InitiatedBy.user.userPrincipalName)
| join kind=inner compromised on UserPrincipalName
| where TimeGenerated between (SuccessTime .. (SuccessTime + 6h))
| project TimeGenerated, UserPrincipalName, IPAddress, OperationName,
Target = tostring(TargetResources[0].displayName)
Tune the thresholds to your tenant. Result code 50126 is an invalid username or password; a source that fails against many accounts and then succeeds against one is worth an analyst's attention even before any change is made.
KQL: Sign-ins from Anonymizing Infrastructure
SigninLogs
| where TimeGenerated > ago(7d) and ResultType == "0"
| where RiskEventTypes_V2 has "anonymizedIPAddress"
| project TimeGenerated, UserPrincipalName, IPAddress, AppDisplayName,
RiskLevelDuringSignIn, ConditionalAccessStatus
Automated Response
Automation rules and playbooks turn detections into containment. Typical actions for a high-confidence identity incident are revoking the user's refresh tokens and sessions, disabling the account, confirming the user as compromised in ID Protection so risk-based policies apply, and removing any credential added during the incident window. Keep a human approval step for actions against privileged or service accounts, where an automatic disable can cause an outage. Test playbooks regularly; expired connections and changed permissions break them silently.
Common Mistakes
- Collecting interactive sign-ins only and missing non-interactive and service principal activity.
- Matching on partial operation names that do not exist, so the rule never fires and nobody notices.
- No tuning loop: noisy rules get disabled instead of improved.
- Retention shorter than the investigation window, so evidence is gone when it is needed.
- Hunting without recording results, so the same ground is covered repeatedly and nothing becomes a detection.
Where to Start
Confirm that all of the Entra log tables above are flowing into Sentinel and check their retention. Deploy the credential-addition rule as a scheduled analytics rule, run the spray-correlation query as a weekly hunt, and build one playbook that revokes sessions for a confirmed compromised user. Expand from there, one hypothesis at a time.