Attackers do not hack in anymore. They log in. Identity is the new perimeter, and most detection rule sets were written for a network-centric world that stopped matching how breaches actually start.
Credential theft, MFA fatigue, and session token replay now account for the majority of initial access in cloud-first environments. None of these techniques trip a firewall rule. All of them show up in your identity provider’s logs — if you know what to look for.
This guide walks through four identity attack patterns that generic “failed login” alerts miss, with detection logic you can adapt to Okta, Entra ID, or any identity provider that exports structured authentication events.
The short version
| Attack pattern | Why signature-based rules miss it |
|---|---|
| Impossible travel | Single-event rules only see one login at a time, not the sequence |
| MFA fatigue (push bombing) | Each push denial looks like normal user behavior in isolation |
| Session token replay | The login itself is legitimate — the session is stolen after auth |
| Post-auth privilege pivot | Happens in the app layer, not the identity provider’s failure logs |
Pattern 1: Impossible travel
A user authenticates from Tel Aviv, then nine minutes later authenticates again from a location that is not physically reachable in that window. Most teams either skip this check or implement it as a hard distance/time threshold, which produces constant false positives from VPNs and mobile carrier IP reassignment.
The fix is to treat it as a stateful, session-aware check rather than a single-event rule:
on every successful authentication event:
fetch last_successful_login for user_id (last 24h, same idp)
if last_successful_login exists:
distance_km = geo_distance(current.geo_coords, last.geo_coords)
elapsed_hr = (current.timestamp - last.timestamp) / 3600
max_plausible_speed_kmh = 900 # commercial flight, generous
if distance_km / elapsed_hr > max_plausible_speed_kmh:
if not (current.asn == last.asn and is_known_vpn_range(current.source_ip)):
emit_finding(
rule = "impossible_travel",
severity = "high",
mitre = "T1078 - Valid Accounts",
user = user_id,
evidence = {distance_km, elapsed_hr, from_geo: last.geo_coords, to_geo: current.geo_coords}
)
store current as last_successful_login for user_id
The ASN and known-VPN-range exception matters more than the speed threshold itself. Tune it against your own SSO’s VPN and remote-access ranges before you turn this on for everyone, or you will spend a week muting your own remote workforce.
Pattern 2: MFA fatigue / push bombing
An attacker with a valid password sends a burst of push notifications hoping the user approves one out of annoyance or confusion. Each individual push denial event is unremarkable. The pattern only exists in aggregate, over a short window, per user.
window = 10 minutes
on mfa_challenge_event where result in (denied, timeout):
count = count(mfa_challenge_event where user_id = event.user_id
and result in (denied, timeout)
and timestamp within window)
if count >= 5:
emit_finding(
rule = "mfa_push_bombing",
severity = "critical",
mitre = "T1621 - Multi-Factor Authentication Request Generation",
user = event.user_id,
evidence = {denied_count: count, window_minutes: 10}
)
Pair this with a second rule for the far more dangerous outcome: a burst of denials immediately followed by one approval. That sequence — not the denials alone — is the highest-confidence signal that someone got worn down into approving an attacker’s push.
Pattern 3: Session token replay
This is the one most teams have no coverage for at all. The authentication event is completely legitimate — the attacker never touched the login form. They stole a session cookie or bearer token (via malware, a proxy phishing kit, or an infostealer log) and are replaying it from different infrastructure entirely.
You cannot detect this from auth events alone. You need to correlate the session identifier across the full lifetime of the session, not just at creation:
on every authenticated request event (not just login):
session = lookup_session(event.session_id)
if session exists:
if event.source_ip != session.last_seen_ip:
if geo_distance(event.geo_coords, session.last_seen_geo) > 500km:
emit_finding(
rule = "session_anomaly_possible_token_theft",
severity = "critical",
mitre = "T1550.004 - Use Alternate Authentication Material: Web Session Cookie",
session_id = event.session_id,
evidence = {original_ip: session.last_seen_ip, new_ip: event.source_ip}
)
session.last_seen_ip = event.source_ip
session.last_seen_geo = event.geo_coords
This requires your identity provider or application layer to log activity events tied to a stable session identifier, not just login/logout. If your current pipeline only ingests authentication events and drops everything in between, this is the gap to close first — it is worth more than another dozen login-failure rules.
Pattern 4: Post-auth privilege pivot
Once inside, attackers frequently touch identity administration functions early — adding themselves to a privileged group, registering a new MFA factor, or creating an API token. These are low-volume, high-signal events that deserve their own priority tier rather than getting buried in general audit noise.
| Priority | Event category | Why |
|---|---|---|
P1 | New MFA factor enrolled outside self-service onboarding window | Classic account-takeover persistence move |
P1 | User added to privileged group by a non-admin-workflow actor | Direct privilege escalation |
P2 | New API token or long-lived credential created | Persistence mechanism, lower immediate blast radius |
P3 | Password reset initiated from a new device/location | Often legitimate, worth a lower-urgency review queue |
Building this without a big platform investment
None of the four patterns above require a specialized identity threat detection product. You need three things: your identity provider’s audit and authentication event stream, a place to hold short-lived per-user and per-session state (a simple key-value store is enough — you are not running analytics, just lookups), and a rules engine that can evaluate against that state. Open, vendor-neutral rule formats like Sigma are a reasonable way to express and share these patterns across teams without locking the logic to one platform.
Final thought
Network-perimeter thinking dies hard, but the data already shows where the attacks are landing. If your detection coverage is still weighted toward failed logins and firewall denies, you are optimizing for the attack path that matters least in 2026. Start with session token replay — it is the pattern with the least existing coverage and the highest payoff.
If you want help mapping these patterns against your own identity provider’s log schema, contact us.