Projects / BehaveGuard

BehaveGuard

Continuous biometric authentication from how you type and move your mouse. BiLSTM + TCN fusion, async retraining over Redis Streams.

Demo

A recording of the local app on the real development data: log in, open the admin dashboard (similarity matrix, versus-mode radar, charts), then the candidate-selection and consent screens. The capture tasks were not run, because scripted behaviour would not be real.

Overview

BehaveGuard is a behavioural-biometrics authentication system. It learns how a person types and moves a cursor, then answers two questions: is this session really this profile (1:1 verification), and which of several profiles is it closest to (1:N identification).

It is built as a full application: a FastAPI backend, PostgreSQL with pgvector, Redis, an RBF-SVM and centroid scorer, an experimental BiLSTM plus TCN fusion model that retrains in the background, and a Next.js app with a consent flow and an admin dashboard.

On the development data, with time windows held out, a Random Forest identifies the right person first 96% of the time (100% within the top three) with a 2% equal error rate, and the tuned SVM scores 82%. Keyboard alone reaches 78% and mouse alone 70%, while using both reaches 82%, so combining them helps.

This is research-scale work, and the numbers should be read that way: the development set is 10 sessions from 9 people, so the results show that the pipeline works, not that it is ready to protect real accounts. The demo shows the app running locally on that dataset, with the nine profiles renamed Profile 1 to 9 for privacy.

What it does

Screenshots

The admin dashboard with profile counts, the review queue, enrollment depth and the profile similarity matrix
The admin dashboard: counts, the review queue, enrollment depth per profile and the similarity matrix.
The profile similarity matrix, with each profile compared to every other
Profile similarity: each profile scores 100 against itself and between 31 and 68 against the others.
Versus mode comparing four profiles on a radar chart with raw measurements
Versus mode: up to four profiles on a radar of typing speed, steadiness, rhythm, precision, cursor control and agility, with the raw measurements below.
Candidate selection with three profiles chosen for a comparison
Candidate selection for 1:N identification. The app tells you how many more samples each profile needs.
The consent screen explaining what the test records
The consent screen: it lists what is recorded and says typed text is not stored.

How it works

Interactive diagram · 9 steps
sample raw events features vectors promote job limits reads A Next.js app. After a consent screen it runs a typing test and three mouse tasks (click dots, drag, track). It records key identity and press/release timing, cursor position and speed, and click accuracy. Typed text is not stored, and nothing is sent until every task finishes.Capture appconsent, typing, mouse1 The backend handles JWT login (with optional Google sign-in), enrollment, 1:1 verification and 1:N identification. It rate-limits logins and verifications, five a minute by default.FastAPIauth, enroll, verify2 Raw keystroke and mouse events become 142 engineered features, such as dwell and flight timing, typing speed, cursor speed, click error and drag success. Each session is also cut into temporal windows.ƒFeatures142 engineered3 A robust scaler with centroid and RBF-SVM scoring gives a similarity to each profile and refits inline on every enrollment. An experimental BiLSTM (keyboard) plus TCN (mouse) fusion model is used once enough repeated sessions exist.ScoringSVM + centroid + neural4 Postgres with pgvector stores profiles, sessions with their features and embeddings, the log of automatic profile merges (each reversible) and security alerts.PostgreSQLprofiles, sessions, pgvector5 Neural retraining runs in the background. A candidate model is trained on a held-out split and replaces the live model only if it passes the promotion gate, so a bad retrain cannot degrade verification.ƒRetrain workerpromotion gate6 Redis holds the per-minute rate-limit counters and a stream of retraining jobs. If a worker crashes mid-job, the unacknowledged job is reclaimed by the next poll instead of being lost.Redisrate limits, job stream7 Passive signals only: brute force (repeated rate-limit blocks), replay suspected (an identical raw payload seen before) and far-spike (scores clustering just under the accept threshold). They raise alerts for a human and never block the request themselves.Security signalsalerts, never blocks8 Shows enrollment depth, a profile similarity matrix, a versus-mode radar of up to four profiles with raw measurements, retraining jobs and open security alerts, with blacklist and delete controls.Admin dashboardsimilarity, alerts9
Pick a stepHover, focus or tap any shape to see what it does.
From a captured sample to a score and a dashboard. Dashed arrows are the background jobs and counters in Redis. Editable source (.excalidraw)
  1. You consent, then the capture app records a typing test and three mouse tasks and sends the timing data once everything is finished.
  2. The backend turns the raw events into 142 features, and the scorer compares them with each profile's centroid and a trained RBF-SVM.
  3. Postgres keeps the profiles, sessions and embeddings, and a Redis stream queues background retraining.
  4. The retrain worker trains a neural candidate on a held-out split and promotes it only if it beats the live model. Security signals watch for brute force, replay and probing.
  5. The admin dashboard reads it all: similarity between profiles, comparisons, jobs and open alerts.

Install and try it

BehaveGuard needs Docker, Python 3.12 with uv, and Node. The dataset is private and not in the repository, so you need your own recorded sessions to import.

  1. Start Postgres and Redis
    git clone https://github.com/mkgstf/behaveguard.git
    cd behaveguard
    docker compose up -d
  2. Install and create the schema
    uv sync
    uv run alembic upgrade head
  3. Import data and start the backend

    The API runs on port 8000. Retraining runs in a background thread locally.

    uv run behaveguard import-xlsx Behaveguard-client.xlsx
    uv run behaveguard serve
  4. Start the frontend

    Open http://localhost:3000. Register an account first.

    cd behaveguard-client
    npm install
    npm run dev
  5. Make yourself an admin

    There is no admin sign-up route, by design.

    uv run behaveguard promote-admin you@example.com --role platform_admin

Notes

All projects · Home