Repository navigation
v0.1.0 — Zero Trust Guard
Self-hosted API security gateway. Every HTTP/HTTPS request must carry a token the
gateway verifies — signature → session → account status → device binding → policy.
No token → no response. Built with Node.js + TypeScript across a monorepo, with a
web dashboard, CLI, demo APIs, Docker, tests, and a benchmark.
What's new
Zero Trust Gateway (src/gateway)
- Layered request gate: JWT signature & expiry → server-side session → account status → device binding (
zerotrust.ts), fail-closed - Short-lived HS256 access tokens (default 900s) + rotating refresh tokens (
auth.ts) - Instant revocation of sessions and devices — a revoked session dies even while the token is cryptographically valid
- Policy engine: role requirements, explicit deny rules, real-time per-route rate limits (
policy.ts,configs/policies.json) - Rate limiting: per-IP login (5/min), global per-IP guard, per user+route policy limits; fixed-window counters (
ratelimit.ts) - Reverse proxy on raw
node:httpthat injectsx-ztg-verified,x-ztg-user-id,x-ztg-session-id,x-ztg-device-id,x-ztg-request-idonly after verification (proxy.ts) - Admin control plane: manage sessions, devices, routes, policies; view metrics and audit events
- Audit hub: durable PostgreSQL sink with NDJSON file fallback (
audit.ts) - WebSocket
/ws: live audit events + metrics to the dashboard - CORS + security headers (
nosniff,DENYframing,no-referrer)
Dashboard (dashboard/)
- Next.js + Tailwind + shadCN-style UI pages: overview (live WS feed), login, sessions, devices, audit, routes, policies
CLI (src/cli)
ztg login/logout/status/metrics, plus admin:route,session,device,policy,audit
Interactive React + Express demo (demo-react/, demo-express/)
- "Why do we need Zero Trust if we already have HTTPS?" — live demo with real-token / no-token / forged-token calls and one-click session revocation. See
docs/why-zerotrust-over-https.md.
Infra & quality
- Monorepo:
@ztg/sharedtypes shared by every component - Docker multi-stage build + Compose stack: postgres + valkey + gateway + dashboard + demo + demo-express
- 31 tests passing (unit: jwt/policy/rate-limit/gate; integration: real gateway + upstream end to end)
- Benchmark script + report in
docs/performance.md - Docs: architecture, security, threat model, ADRs, performance, deployment
Security model
- Fail-closed at every identity check; an unavailable session store denies rather than accepts
- Passwords stored as scrypt hashes (
configs/users.json), never plaintext - Refresh tokens are single-use (rotation); revoking a session or device takes effect on the next request
- Known limitations, detailed in
docs/threat-model.md:- Access-token replay is possible within its short window
- Device identity is software-based (no hardware attestation)
/wsstream currently accepts unauthenticated connections (planned fix)- In-box TLS termination not included; terminate HTTPS in front of the gateway
- JWT signing crypto is hand-rolled for learning; production would use a vetted library (e.g.
jose)
Performance (local, indicative)
| Scenario | req/s | p50 | p95 | p99 |
|---|---|---|---|---|
| Direct upstream (baseline) | ~4,500 | ~3.2ms | ~6.6ms | ~14.1ms |
| Gateway — rejected (no token) | ~3,500 | ~4.0ms | ~8.7ms | ~14.9ms |
| Gateway — verified + forwarded | ~2,050 | ~7.1ms | ~13.3ms | ~17.4ms |
Full methodology: docs/performance.md, run npm run bench -w @ztg/gateway.
Getting started
git clone https://github.com/wellparth/ZeroTrust.git
cd ZeroTrust
npm install && npm run buildDocker:
cp .env.example .env # set ZTG_JWT_SECRET
docker compose up --buildDemo credentials: admin/admin123 (admin), user/user123, blocked/blocked123 (suspended).
Contributors
Maintained by Parth Gorde.
Released under the MIT License.