{"id":24068693,"url":"https://github.com/vhscom/private-landing","last_synced_at":"2026-02-15T09:27:16.222Z","repository":{"id":271633266,"uuid":"913883496","full_name":"vhscom/private-landing","owner":"vhscom","description":"🔥 Build authenticated RESTful APIs using Cloudflare Workers, Hono and Turso. Mirror of Private Landing on Codeberg 👇","archived":false,"fork":false,"pushed_at":"2025-02-23T21:19:06.000Z","size":247,"stargazers_count":7,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-23T22:25:30.008Z","etag":null,"topics":["cloudflare-workers","honojs","jwt-authentication","libsql-client","pbkdf2","turso-db","webauthn","wrangler-cli"],"latest_commit_sha":null,"homepage":"https://codeberg.org/vhs/private-landing","language":"TypeScript","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vhscom.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-01-08T14:36:59.000Z","updated_at":"2025-02-23T21:18:51.000Z","dependencies_parsed_at":"2025-01-09T00:27:35.882Z","dependency_job_id":"0b70a5cc-75ca-4243-b9c0-653216b0adac","html_url":"https://github.com/vhscom/private-landing","commit_stats":null,"previous_names":["vhscom/private-landing"],"tags_count":3,"template":true,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vhscom%2Fprivate-landing","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vhscom%2Fprivate-landing/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vhscom%2Fprivate-landing/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vhscom%2Fprivate-landing/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vhscom","download_url":"https://codeload.github.com/vhscom/private-landing/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240927452,"owners_count":19879929,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cloudflare-workers","honojs","jwt-authentication","libsql-client","pbkdf2","turso-db","webauthn","wrangler-cli"],"created_at":"2025-01-09T13:47:05.325Z","updated_at":"2026-02-15T09:27:16.178Z","avatar_url":"https://github.com/vhscom.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n# Private Landing\n\n**Learn authentication by building it right.**\n\n[![License](https://img.shields.io/badge/License-Apache_2.0-blue?style=for-the-badge)](https://opensource.org/licenses/Apache-2.0)\n[![TypeScript](https://img.shields.io/badge/TypeScript-5.8+-3178c6?style=for-the-badge\u0026logo=typescript\u0026logoColor=white)](https://www.typescriptlang.org/)\n[![Cloudflare Workers](https://img.shields.io/badge/Cloudflare-Workers-f38020?style=for-the-badge\u0026logo=cloudflareworkers\u0026logoColor=white)](https://workers.cloudflare.com/)\n\u003cbr\u003e\n[![CI](https://img.shields.io/github/actions/workflow/status/vhscom/private-landing/ci.yml?style=for-the-badge\u0026label=CI)](https://github.com/vhscom/private-landing/actions/workflows/ci.yml)\n[![codecov](https://img.shields.io/codecov/c/github/vhscom/private-landing?style=for-the-badge\u0026token=24IDKH0NE1)](https://codecov.io/github/vhscom/private-landing)\n\n**[Live Demo](https://private-landing.vhsdev.workers.dev/)** · **[Threat Model](docs/threat-model.md)** · **[Auth Flows](docs/flows.md)** · **[ADRs](docs/adr/)**\n\n\u003c/div\u003e\n\n---\n\nA 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 (with optional Valkey/Redis caching), and strict TypeScript.\n\nEvery design choice traces back to a standard: [NIST SP 800-63B](https://pages.nist.gov/800-63-3/sp800-63b.html) for credentials, [NIST SP 800-132](https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-132.pdf) for key derivation, [OWASP ASVS](https://owasp.org/www-project-application-security-verification-standard/) for verification, and [RFC 8725](https://datatracker.ietf.org/doc/html/rfc8725) for JWT best practices.\n\n\u003e **Shipping a product?** Use **[Better Auth](https://www.better-auth.com)** 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.\n\n### Why this repo\n\n- **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\n- **NIST + OWASP + RFC references** throughout — learn the *why* behind each decision\n- **250+ tests** including attack-vector suites (token tampering, algorithm confusion, unicode edge cases)\n- **Built for the edge** — runs on Cloudflare Workers with Web Crypto API, no Node.js dependencies\n- **Apache-2.0** — fork it, teach with it, learn from it\n\n## What You'll Find Inside\n\n| Layer | What it does |\n|-------|-------------|\n| **Password storage** | PBKDF2-SHA384 with 128-bit salts, integrity digest, version tracking ([`password-service.ts`](packages/core/src/auth/services/password-service.ts)) |\n| **Session management** | Server-side sessions with device tracking, sliding expiration, max-3-per-user enforcement; optional cache-backed sessions via Valkey/Redis ([`session-service.ts`](packages/core/src/auth/services/session-service.ts), [`cached-session-service.ts`](packages/core/src/auth/services/cached-session-service.ts)) |\n| **JWT dual-token pattern** | 15-min access + 7-day refresh tokens, session-linked for revocation ([`token-service.ts`](packages/core/src/auth/services/token-service.ts)) |\n| **Auth middleware** | Automatic refresh flow, explicit HS256 pinning, `typ` claim validation ([`require-auth.ts`](packages/core/src/auth/middleware/require-auth.ts)) |\n| **Secure cookies** | HttpOnly, Secure, SameSite=Strict, Path=/ ([`cookie.ts`](packages/core/src/auth/utils/cookie.ts)) |\n| **Security headers** | HSTS, CSP, CORP/COEP/COOP, Permissions-Policy, fingerprint removal ([`security.ts`](packages/core/src/auth/middleware/security.ts)) |\n| **Input validation** | Zod schemas with NIST-compliant password policy (length only, no complexity rules) |\n| **Attack-vector tests** | JWT tampering, algorithm confusion, type confusion, unicode edge cases, info-disclosure checks |\n\n## Production Next Steps\n\nThis 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.\n\n\u003e For most real-world projects, use [Better Auth](https://www.better-auth.com) instead of building these yourself.\n\n### Critical — Add Before Real Users\n\n| Feature | Why It Matters | Standard / Reference |\n|---------|---------------|---------------------|\n| Rate limiting | Prevents brute-force login and credential-stuffing attacks — the cache layer ([ADR-003](docs/adr/003-cache-layer-valkey.md)) is available as a foundation | [OWASP ASVS V2.2.1](https://owasp.org/www-project-application-security-verification-standard/) |\n| Account lockout / throttling | Slows automated attacks without full rate-limiting infra | [NIST SP 800-63B §5.2.2](https://pages.nist.gov/800-63-3/sp800-63b.html) |\n| Password change endpoint | Users cannot recover from compromised credentials without it | [OWASP ASVS V2.1.6](https://owasp.org/www-project-application-security-verification-standard/) |\n| Breached-password checking | Prevents use of passwords known to be in public breach dumps | [NIST SP 800-63B §5.1.1.2](https://pages.nist.gov/800-63-3/sp800-63b.html), [HIBP API](https://haveibeenpwned.com/API/v3) |\n\n### High Priority — Production Confidence\n\n| Feature | Why It Matters | Standard / Reference |\n|---------|---------------|---------------------|\n| 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](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html) |\n| 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](https://datatracker.ietf.org/doc/html/rfc6819#section-5.2.2.3) |\n| `aud` claim in JWTs | Prevents token from one service being accepted by another sharing the same secret | [RFC 7519 §4.1.3](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.3), [RFC 8725 §3.9](https://datatracker.ietf.org/doc/html/rfc8725#section-3.9) |\n| Audit logging | Enables incident response, anomaly detection, and compliance | [OWASP Logging Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html) |\n| CSP nonces for inline scripts | Current CSP uses `'unsafe-inline'`; nonces eliminate inline-script XSS vectors | [MDN CSP script-src](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src) |\n\n### Medium Priority — As Product Scales\n\n| Feature | Why It Matters | Standard / Reference |\n|---------|---------------|---------------------|\n| TOTP multi-factor auth | Adds a second factor for high-value accounts | [RFC 6238](https://datatracker.ietf.org/doc/html/rfc6238), [NIST SP 800-63B §5.1.4](https://pages.nist.gov/800-63-3/sp800-63b.html) |\n| WebAuthn / passkeys | Phishing-resistant authentication using platform authenticators | [WebAuthn Level 2](https://www.w3.org/TR/webauthn-2/) |\n| OAuth / social login | Reduces friction, avoids password fatigue | [RFC 6749](https://datatracker.ietf.org/doc/html/rfc6749) |\n| Magic links / OTP | Passwordless option for low-risk flows | [NIST SP 800-63B §5.1.3](https://pages.nist.gov/800-63-3/sp800-63b.html) |\n| Session analytics | Device tracking, concurrent-session visibility, anomaly detection | [OWASP Session Management Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html) |\n| Signing key rotation | Allows periodic secret rotation without invalidating all sessions | [RFC 7517 (JWK)](https://datatracker.ietf.org/doc/html/rfc7517) |\n\n### Advanced — Enterprise / High-Security\n\n| Feature | Why It Matters | Standard / Reference |\n|---------|---------------|---------------------|\n| DPoP / token binding | Binds tokens to the client's TLS connection, preventing exfiltration replay | [RFC 9449 (DPoP)](https://datatracker.ietf.org/doc/html/rfc9449) |\n| Multi-tenancy | Isolates user pools, secrets, and policies per tenant | Application-specific |\n| Geo-fencing / IP reputation | Blocks logins from unexpected regions or known-bad IPs | [OWASP ASVS V2.2.3](https://owasp.org/www-project-application-security-verification-standard/) |\n| Adaptive authentication | Steps up auth requirements based on risk signals (device, location, behavior) | [NIST SP 800-63B §6](https://pages.nist.gov/800-63-3/sp800-63b.html) |\n| 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](https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html) |\n\nAll of these are excellent reasons to reach for [Better Auth](https://www.better-auth.com) instead.\n\n## Repository Structure\n\n```text\n.\n├── apps/\n│   └── cloudflare-workers/    # Example Worker + Hono routes\n├── packages/\n│   ├── core/                  # Auth services, middleware, crypto utilities\n│   ├── infrastructure/        # DB client + utilities\n│   ├── schemas/               # Zod schemas\n│   └── types/                 # Shared TypeScript types\n└── docs/\n    ├── adr/                   # Architecture Decision Records\n    └── audits/                # Security audits\n```\n\n## Getting Started\n\n```bash\n# Clone and install\ngit clone https://github.com/vhscom/private-landing.git\ncd private-landing\nbun install\n\n# Build packages\nbun run build\n\n# Start dev server\nbun run dev\n```\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for detailed setup and testing instructions.\n\n## Using with AI\n\nThis repository includes a [`CLAUDE.md`](CLAUDE.md) file that provides context for AI assistants. When using Claude Code, Cursor, or similar AI-powered development tools:\n\n1. The AI will automatically read `CLAUDE.md` for project context\n2. Architecture Decision Records in `docs/adr/` explain design choices\n3. Security audits in `docs/audits/` document the security posture\n4. Tests demonstrate expected behavior and edge cases\n\nThe codebase is designed to be AI-readable with clear module boundaries, comprehensive types, and descriptive naming.\n\n## License\n\n[Apache-2.0](LICENSE)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvhscom%2Fprivate-landing","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvhscom%2Fprivate-landing","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvhscom%2Fprivate-landing/lists"}