Preventing Account Takeover with IP Intelligence
What Account Takeover Looks Like
Account takeover (ATO) is the process by which an attacker gains unauthorised access to a legitimate user's account. It is one of the most prevalent and damaging forms of fraud across all digital products — from SaaS platforms to ecommerce stores to financial services.
The three most common attack vectors are:
Credential stuffing — Attackers purchase leaked username/password databases (there are billions of credentials available on dark-web markets) and replay them against your login endpoint at scale using automated tooling like OpenBullet or Sentry MBA. Success rates of 0.1–2% are typical, which means a database of 10 million credentials yields 10,000–200,000 compromised accounts.
Brute force — Targeted attacks against specific accounts by cycling through common passwords or patterns. Less common than stuffing but more dangerous for high-value accounts.
Session hijacking — Attackers steal session tokens via phishing, man-in-the-middle attacks, or XSS, then replay the token from a different location. The IP change is the telltale signal.
Why IP Signals Help
Attackers use proxies, VPNs, Tor, and datacenter infrastructure for one reason: to distribute their traffic and avoid IP-based rate limiting. This is also their weakness. Legitimate users almost always authenticate from residential ISPs, mobile data networks, or known corporate IPs. An authentication attempt from a Tor exit node or a known datacenter range is statistically far more likely to be an attacker than a genuine user.
IP intelligence gives you a high-confidence signal at the point of login — before the user has even entered their password — at sub-5ms latency with a cached result.
Where to Check IP in Your Auth Flow
Pre-login check — Look up the IP before accepting the password. If the IP is Tor or has a risk score above 90, you can reject the attempt outright or force a CAPTCHA before proceeding. This stops automated tools that don't handle interactive challenges.
Post-login anomaly detection — Compare the IP of the new session against the user's historical session IPs. A user who always authenticates from Germany suddenly logging in from a Malaysian datacenter IP is a strong ATO signal even if the password is correct.
2FA challenge trigger — Rather than blocking suspicious IPs outright, use them as a trigger for step-up authentication. An elevated-risk IP (score 50–80) should require TOTP or an email OTP even if the user doesn't normally have 2FA enabled.
Python / FastAPI Middleware Example
import httpx
from fastapi import Request, HTTPException
PREDAX_KEY = "prdx_YOUR_KEY"
async def get_ip_risk(ip: str) -> dict:
async with httpx.AsyncClient() as client:
r = await client.post(
"https://predax.io/api/v1/check/ip",
headers={"X-API-Key": PREDAX_KEY},
json={"ip": ip},
timeout=2.0,
)
return r.json()
async def login_ip_guard(request: Request) -> None:
"""FastAPI dependency — call before processing login credentials."""
client_ip = request.client.host
result = await get_ip_risk(client_ip)
classification = result.get("classification", {})
risk = classification.get("risk_score", 0)
is_tor = classification.get("is_tor", False)
is_datacenter = classification.get("is_datacenter", False)
# Hard block: Tor or datacenter + very high risk
if is_tor or (is_datacenter and risk >= 85):
raise HTTPException(
status_code=403,
detail="Login not permitted from this network.",
)
# Attach risk data to request state for downstream use
request.state.ip_risk = resultThen in your login route:
from fastapi import Depends
@router.post("/login")
async def login(
credentials: LoginSchema,
request: Request,
_: None = Depends(login_ip_guard),
):
# ip_risk is available on request.state
ip_risk = request.state.ip_risk
user = authenticate_user(credentials)
if ip_risk["classification"]["risk_score"] >= 50:
# Require MFA regardless of user's normal preference
return {"mfa_required": True, "session_token": issue_temp_token(user)}
return {"access_token": issue_full_token(user)}Step-Up Auth Strategy
A layered approach avoids both under-protection and over-blocking:
| Risk score | Action |
|---|---|
| 0–30 | Normal login flow |
| 30–50 | Log the attempt; apply tighter rate limits |
| 50–75 | Require email OTP or TOTP even if not normally required |
| 75–90 | Require MFA + notify account owner by email |
| 90–100 | Block and alert security team |
This approach means that a legitimate user who occasionally uses a privacy VPN gets an MFA challenge rather than a hard block, while automated credential stuffing tools (which don't handle interactive auth flows) are stopped entirely.
Trusted IP Whitelisting
For B2B products, allow users to register trusted IP ranges (their office IP, home IP, corporate VPN exit). Authentication from a whitelisted IP bypasses IP risk checks entirely. This removes friction for power users while maintaining protection for everyone else.
Store trusted IPs as CIDR ranges against the user record and check them before the IP reputation lookup. Cache the whitelist check in Redis with a short TTL to keep latency low.
Combining with Rate Limiting
IP reputation and rate limiting are complementary, not substitutes. Use rate limiting to stop brute force (5 failed attempts per IP per 15 minutes). Use IP reputation to stop stuffing from distributed sources. Use session anomaly detection to catch post-login ATO. Together, these three layers cover the vast majority of ATO attack patterns.
Related guides
- Credential stuffing: the complete guide — the attack pattern that drives most ATO attempts.
- How IP risk scoring works — the score most ATO step-up rules are keyed off.
- How to detect VPN users — attackers almost always tunnel; here's how to spot them.
- ASN-based blocking explained — why ASN reputation usually beats per-IP blocking for ATO traffic.
See pricing to wire IP intelligence into your login flow today.
