A from-scratch authentication reference implementation for Cloudflare Workers — PBKDF2 password hashing, JWT dual-token sessions, constant-time comparison, and sliding expiration — all wired together with Hono, Turso, and strict TypeScript.
Every design choice traces back to a standard: NIST SP 800-63B for credentials, NIST SP 800-132 for key derivation, OWASP ASVS for verification, and RFC 8725 for JWT best practices.
Shipping a product? Use Better Auth instead — it covers OAuth, passkeys, MFA, rate limiting, and more out of the box with an active plugin ecosystem. This repo exists to teach you how auth works, not to replace a production library.
- Read the code, not just the docs — every security property (timing-safe rejection, session-linked revocation, algorithm pinning) is implemented and tested, not just described
- NIST + OWASP + RFC references throughout — learn the why behind each decision
- 250+ tests including attack-vector suites (token tampering, algorithm confusion, unicode edge cases)
- Built for the edge — runs on Cloudflare Workers with Web Crypto API, no Node.js dependencies
- Apache-2.0 — fork it, teach with it, learn from it
| Layer | What it does |
|---|---|
| Password storage | PBKDF2-SHA384 with 128-bit salts, integrity digest, version tracking (password-service.ts) |
| Session management | Server-side sessions with device tracking, sliding expiration, max-3-per-user enforcement (session-service.ts) |
| JWT dual-token pattern | 15-min access + 7-day refresh tokens, session-linked for revocation (token-service.ts) |
| Auth middleware | Automatic refresh flow, explicit HS256 pinning, typ claim validation (require-auth.ts) |
| Secure cookies | HttpOnly, Secure, SameSite=Strict, Path=/ (cookie.ts) |
| Security headers | HSTS, CSP, CORP/COEP/COOP, Permissions-Policy, fingerprint removal (security.ts) |
| Input validation | Zod schemas with NIST-compliant password policy (length only, no complexity rules) |
| Attack-vector tests | JWT tampering, algorithm confusion, type confusion, unicode edge cases, info-disclosure checks |
This project intentionally omits features that are outside its educational scope. If you're extending this code toward production (or evaluating what a production auth system requires), the tables below organize the gaps by priority tier.
For most real-world projects, use Better Auth instead of building these yourself.
| Feature | Why It Matters | Standard / Reference |
|---|---|---|
| Rate limiting | Prevents brute-force login and credential-stuffing attacks | OWASP ASVS V2.2.1 |
| Account lockout / throttling | Slows automated attacks without full rate-limiting infra | NIST SP 800-63B §5.2.2 |
| Password change endpoint | Users cannot recover from compromised credentials without it | OWASP ASVS V2.1.6 |
| Breached-password checking | Prevents use of passwords known to be in public breach dumps | NIST SP 800-63B §5.1.1.2, HIBP API |
| Feature | Why It Matters | Standard / Reference |
|---|---|---|
| CSRF protection (if SameSite relaxed) | SameSite=Strict currently prevents CSRF; if changed to Lax for UX, an explicit token is needed | OWASP CSRF Cheat Sheet |
| Refresh token rotation | Detects token theft — if a rotated-out refresh token is replayed, revoke the entire session family | RFC 6819 §5.2.2.3 |
aud claim in JWTs |
Prevents token from one service being accepted by another sharing the same secret | RFC 7519 §4.1.3, RFC 8725 §3.9 |
| Audit logging | Enables incident response, anomaly detection, and compliance | OWASP Logging Cheat Sheet |
| CSP nonces for inline scripts | Current CSP uses 'unsafe-inline'; nonces eliminate inline-script XSS vectors |
MDN CSP script-src |
| Feature | Why It Matters | Standard / Reference |
|---|---|---|
| DPoP / token binding | Binds tokens to the client's TLS connection, preventing exfiltration replay | RFC 9449 (DPoP) |
| Multi-tenancy | Isolates user pools, secrets, and policies per tenant | Application-specific |
| Geo-fencing / IP reputation | Blocks logins from unexpected regions or known-bad IPs | OWASP ASVS V2.2.3 |
| Adaptive authentication | Steps up auth requirements based on risk signals (device, location, behavior) | NIST SP 800-63B §6 |
| PBKDF2 iteration upgrade or Argon2id | OWASP recommends 210,000 PBKDF2-SHA512 iterations (Cloudflare limits to 100k); Argon2id is memory-hard | OWASP Password Storage Cheat Sheet |
All of these are excellent reasons to reach for Better Auth instead.
.
├── apps/
│ └── cloudflare-workers/ # Example Worker + Hono routes
├── packages/
│ ├── core/ # Auth services, middleware, crypto utilities
│ ├── infrastructure/ # DB client + utilities
│ ├── schemas/ # Zod schemas
│ └── types/ # Shared TypeScript types
└── docs/
├── adr/ # Architecture Decision Records
└── audits/ # Security audits
# Clone and install
git clone https://github.com/vhscom/private-landing.git
cd private-landing
bun install
# Build packages
bun run build
# Start dev server
bun run devSee CONTRIBUTING.md for detailed setup and testing instructions.
This repository includes a CLAUDE.md file that provides context for AI assistants. When using Claude Code, Cursor, or similar AI-powered development tools:
- The AI will automatically read
CLAUDE.mdfor project context - Architecture Decision Records in
docs/adr/explain design choices - Security audits in
docs/audits/document the security posture - Tests demonstrate expected behavior and edge cases
The codebase is designed to be AI-readable with clear module boundaries, comprehensive types, and descriptive naming.