Skip to content

Nabil201-ctrl/session-watch

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

session-watch

Looks at a stream of login events and asks: does this user's path make sense?

I wrote this because failed-login counters alone miss the interesting cases — same password accepted in Lagos and London 45 minutes apart. That isn't a fat-finger. That's either account sharing, a VPN story worth checking, or session theft.

Python does the analysis. TypeScript wraps it for an HTTP POST /analyze and a small CLI.


Checks

1. Impossible travel

Two successful logins, different cities, short gap.
Haversine distance → km → km/h. If speed is past ~800 km/h (demo jet ceiling), raise impossible_travel.

Cities are a fixed table in engine/geo.py so the project runs offline. Swap for real GeoIP later if you wire this into production logs.

2. Fail burst

Enough failed attempts on one account (default 5+) → fail_burst.
Could be the user locked out. Could be stuffing. Either way it should show up.

3. Device churn

Many distinct device_ids in the window → device_churn. Shared accounts and attackers rotating devices both look like this.

Findings are sorted with high severity first.


Flowchart

flowchart TD
    L[login events JSON] --> T[TypeScript api]
    T -->|stdin JSON| P[engine/cli.py]
    P --> A[analyzer.py]
    A --> G[geo.py haversine]
    A --> F1[impossible travel]
    A --> F2[fail bursts]
    A --> F3[device churn]
    F1 --> M[merge findings]
    F2 --> M
    F3 --> M
    M --> O[JSON findings]
    O --> T
    T --> R[API response / terminal]
Loading

Structure

session-watch/
  engine/
    geo.py
    analyzer.py
    cli.py
  api/
    bridge.ts
    server.ts
    analyze.ts
  sample_data/logins.json
  tests/

Build steps

git clone https://github.com/Nabil201-ctrl/session-watch.git
cd session-watch

Direct (Python)

python3 engine/cli.py -i sample_data/logins.json

Through TypeScript

cd api
npm install
npx ts-node analyze.ts ../sample_data/logins.json

API

npx ts-node server.ts
# listens on 3855

curl -s -X POST http://127.0.0.1:3855/analyze \
  -H 'content-type: application/json' \
  -d @../sample_data/logins.json

Test the travel case

python3 -c "
import sys
from pathlib import Path
sys.path.insert(0, str(Path('engine').resolve()))
sys.path.insert(0, str(Path('tests').resolve()))
from test_analyzer import test_lagos_to_london_is_flagged
test_lagos_to_london_is_flagged()
print('ok')
"

Sample set

The included logins.json is hand-written to trigger each path:

  • u_nabil — Lagos then London under an hour
  • u_sara — five fails from mixed IPs
  • u_ken — four devices, same city

When I change thresholds I re-run this file first before touching real data.


Why two languages

I already had the math in Python and didn't want to port haversine + event grouping into TS just for an endpoint. Spawning the engine keeps risk logic in one place. Tradeoff: process startup cost. Fine for batch/demo traffic; for hot path you'd keep a long-lived worker.


Roadmap (personal)

  • Real GeoIP lookup
  • Single combined risk score
  • Hook “high” findings into a payment risk check
  • MFA step-up callback

About

Login anomaly detection: impossible travel, fail bursts, and device churn (Python + TypeScript)

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors