sysop@hub:~/tools/signin-analyzer$
signin-analyzer
Drop an Entra ID sign-in log export. You get a triage report: what looks like an attack, which accounts are affected, what to do next, and a KQL query to keep hunting. The file is read by your browser and never uploaded, so it also works offline.
column mapping
Columns are matched by name. If your export uses different headers, point each field at the right column and the report re-runs.
getting the export
| Source | How |
|---|---|
| Entra admin center | Monitoring & health, Sign-in logs, set the date range, Download, CSV. Interactive and non-interactive sign-ins are separate files; analyse them one at a time. |
| Microsoft Graph PowerShell | Get-MgAuditLogSignIn -All | ConvertTo-Json -Depth 6 | Out-File signins.json (PowerShell 7, needs AuditLog.Read.All) |
| One script for both analyzers | Generate it in the script generator: a read-only export of Conditional Access policies and sign-ins. |
| Log Analytics / Sentinel | SigninLogs | where TimeGenerated > ago(7d), then Export, CSV (all columns) |
what it checks
| Check | Triggers when |
|---|---|
| Password spray | One IP fails with a wrong password, lockout or unknown user against 5 or more accounts. Critical if that IP then signs in successfully. |
| Password guessing | 10 or more wrong-password or lockout events on one account. Critical if an address with 3 or more of those failures later succeeds. |
| Country switch | Two successful sign-ins by one account from different countries and different IPs within 2 hours. |
| MFA fatigue | 5 or more failed or denied MFA prompts (500121) for one account. Critical if a sign-in succeeds during or within an hour after. |
| Legacy authentication | Any sign-in over IMAP, POP, SMTP, ActiveSync or "Other clients". High if any succeed. |
| Scripted clients | User agents of HTTP libraries and tools (python-requests, axios, curl, BAV2ROPC and similar). High if any succeed. |
| Rare countries | Countries with under 2% of successful sign-ins, once there are at least 50 successes. |
| Single-factor success | Successful sign-ins where the authentication requirement was single-factor. |
| Disabled and unknown accounts | Attempts on disabled accounts (50057), or 5 or more different non-existent usernames (50034). |
| Conditional Access blocks | Sign-ins stopped by policy (53003, 53000, 53001). The password was correct in these cases. |
These are heuristics, the same first-pass questions an analyst asks of a sign-in log. They produce leads, not verdicts: a VPN looks like a country switch, a forgotten phone looks like password guessing. Location is only as good as the IP geolocation in the export, and compared at country level. A check that needs a column your export lacks is listed as not checked instead of silently passing. This is no replacement for Entra ID Protection or a SIEM that watches continuously.
Related: AADSTS error lookup incident runbook generator compromised account checklist KQL cheat sheet