Dependency-free challenge–response sign-in for Node.js and modern browsers. Uses Web Crypto (ECDSA P-256) and OPFS for the private key — no Passkeys / WebAuthn.
npm startOpen http://localhost:8000.
Edit config.js if you change host, port, or deploy over HTTPS.
Create an account (signs you in):
POST /api/register/options
crypto.subtle.generateKey → save PKCS8 private key to OPFS
sign { type, origin, challenge, credentialId }
POST /api/register/verify → session cookie
Sign in again later:
POST /api/login/options
load private key from OPFS → crypto.subtle.sign
POST /api/login/verify → session cookie
Session:
GET /api/session
POST /api/logout
- Browser creates an ECDSA P-256 key pair, keeps the private key in OPFS
(
keys/private.pkcs8), and sends the public key to the server. - Both register and login sign a small JSON payload:
type,origin,challenge, andcredentialId. - Server checks challenge, origin, and the signature, then sets an HttpOnly session cookie.
- Public keys live in
credentials.json(survive restarts). Challenges and sessions stay in memory.
App code: static/crypto.js, lib/auth.js.