Passkeys only
Discoverable WebAuthn login with no username field. Choose platform or roaming authenticators, require user verification, and decide whether synced passkeys are allowed.
Passkey-only OpenID Connect provider
Fractessa is a self-hosted OpenID Connect provider and OAuth 2.0 authorization server where people sign in with passkeys only. No passwords, in any flow. It runs entirely on Cloudflare: one Worker with D1, R2, Durable Objects, Queues and Images.
Tessera hospitalis
Romans sealed hospitality with a token broken in two. Each host kept one half, and years later the halves fitting together proved who you were. A passkey works the same way: the private half never leaves your device, the public half lives on the server, and only the pair signs you in.
Fractessa is built around that pair. Recovery options exist only to get you back to a passkey, never to replace it.
Discoverable WebAuthn login with no username field. Choose platform or roaming authenticators, require user verification, and decide whether synced passkeys are allowed.
One-time codes, sign-in links by email, and sign in from another device: the new device shows a code, and a device already signed in approves it with its passkey.
Authorization code with PKCE, rotating refresh tokens, client credentials, device flow, PAR, introspection, userinfo, end session and back-channel logout.
Group-restricted apps, custom claims per user or group, claim mapping policies per client, open or invite-only signup, and optional or required email verification.
Register resource servers with permissions (RFC 8707) and grant them per client, for users or for the client itself. Personal API keys with scopes, renewal and expiry warnings.
Outbound SCIM provisioning, client ID metadata documents (CIMD), federated client credentials from other identity providers, and a full audit log with sign-in notifications.
Point any OpenID Connect client at the discovery document and it finds everything else. Access tokens are signed JWTs, and the signing key belongs to your instance.
Default scopes: openid profile email groups offline_access, plus the scopes of every API you register.
Architecture
Every part of the original single binary maps to a Cloudflare product. One-time tokens are consumed with a single atomic statement, and per-key state lives in Durable Objects.
API, OIDC endpoints, the admin app, cron jobs and queue consumers in a single TypeScript Worker.
Users, clients, sessions, consents and tokens, with migrations applied before every deploy.
Cross-device login with long polling, exact rate limiting, and debounced SCIM syncs.
Durable back-channel logout delivery, with retries and a dead letter queue.
Logos and profile pictures, resized to square PNGs or generated from initials.
Hourly SCIM syncs and signup cleanup; nightly token, session and audit log cleanup.
You need Node.js 22 or newer, a Cloudflare account on Workers Paid, and a domain of your own on Cloudflare: passkeys are bound to the domain, and some password managers refuse *.workers.dev. SMTP is optional.
# install dependencies
make install
# local D1, migrations, http://localhost:1411
make dev
With no users yet, the first visit creates the administrator and their passkey.
npx wrangler login
# D1, R2, queues and secrets
make cf-setup
# checks, tests, build, migrations, deploy
make deploy
Set APP_URL and your custom domain in wrangler.jsonc first. Changing the URL later invalidates every passkey.