eetr-auth
Getting started

Cloudflare template

Fork eetr-auth, configure it for your domain, and deploy your own OAuth 2.1 / OIDC server to the edge.

eetr-auth is designed to be used as a reusable Cloudflare Workers template. Fork it, configure it for your domain, and deploy a fully functional OAuth 2.1 + OpenID Connect server to Cloudflare's edge in minutes.

What you get

  • A production-ready OAuth 2.1 / OpenID Connect authorization server
  • Argon2id password hashing via an isolated Cloudflare Worker
  • An admin dashboard for managing users, clients, and tokens
  • Passkey (WebAuthn) support
  • Multi-factor auth — email OTP (site-wide) and authenticator-app TOTP (per-user, RFC 6238) — plus email verification
  • Cloudflare D1 (SQLite) for persistence and R2 for JWKS, avatars, and site assets
  • A published TypeScript client library (@eetr/eetr-auth-client)

What you provide

RequirementWhere used
Cloudflare account (Workers, D1, R2, Images)All infrastructure
Custom domain (recommended)AUTH_URL, ISSUER_BASE_URL
Resend API keyTransactional email (password reset, MFA, verification)
Terraform CLIProvisioning D1 + R2

Step 1 — Fork or clone

git clone https://github.com/eetr-ai/eetr-auth.git my-auth-server
cd my-auth-server
npm install

Step 2 — Customize the worker name

The auth worker is named eetr-auth by default. To use a custom name, set worker_name in infra/terraform/terraform.tfvars:

worker_name = "my-auth-server"

The Wrangler config is rendered from infra/wrangler.template.jsonc during npm run setup:remote, and the WORKER_SELF_REFERENCE service binding is generated to match worker_name automatically.

Leave argon-hasher's name alone

You do not need to rename argon-hasher — it is a shared internal service and its name is fixed in the ARGON_HASHER service binding.

Step 3 — Configure your domain

Set the domain where the auth server will be accessible — it is used in OAuth flows and email links. Configure these in infra/terraform/terraform.tfvars:

issuer_base_url   = "https://auth.yourdomain.com"
auth_url          = "https://auth.yourdomain.com/api/auth/session"  # full Auth.js session endpoint
jwks_cdn_base_url = "https://cdn.yourdomain.com"

Step 4 — Provision and deploy

See Deployment for the full guide. In summary:

# 1. Provision D1 + R2
cd infra/terraform && terraform init && terraform apply && cd -

# 2. Deploy the password hasher, then run automated setup
npm run deploy:argon-hasher
npm run setup:remote

Harden the seeded admin / admin account immediately after first login.

Customization points

Site identity & branding

Configure under Dashboard → Setup → Site identity:

  • Site title — shown on the sign-in/authorize pages and in emails; also the issuer label users see when they enroll an authenticator app (TOTP).
  • Site logo — image upload (JPEG/PNG/WebP, up to 5 MB) stored in R2.
  • Site URL — the public auth URL; required so transactional email can build working links.
  • CDN URL — optional public base URL used to serve the uploaded logo.
Dashboard Setup page, Site identity tab, with site title, site URL, CDN URL, a site-wide email MFA toggle, and logo upload
Dashboard → Setup → Site identity — title, URLs, logo, and the site-wide email MFA toggle. The Setup page also has Admin API, Environments, Scopes, and Password policies tabs.

Branding scope

Only the title and logo are visual branding — there is no theme/color, font, or favicon customization.

Email

The server uses Resend for transactional email. Templates live in apps/auth/src/lib/email/ — customize the HTML/text there.

Scopes

Default scopes (openid, profile, email) are seeded during db:bootstrap. Add custom scopes in the admin dashboard → Scopes.

Password hashing

The default is argon (Argon2id via the argon-hasher Worker). To use an alternative, set HASH_METHOD in infra/wrangler.template.jsonc and implement the hash interface in apps/auth/src/lib/auth/.

Template boundaries — what is NOT committed

These files contain instance-specific values and are gitignored — you generate them locally:

FileDescription
apps/auth/wrangler.generated.jsoncGenerated from Terraform with real D1/R2 IDs
infra/out/terraform.tf.jsonTerraform output JSON
infra/terraform/terraform.tfvarsYour account ID and resource names
apps/auth/.env.localLocal env vars
apps/auth/.dev.varsWrangler local dev secrets

The committed infra/wrangler.template.jsonc is the template — placeholders get rendered into wrangler.generated.jsonc by the infra scripts.

Updating the template

To pull in upstream changes after you've deployed your instance:

git remote add upstream https://github.com/eetr-ai/eetr-auth.git
git fetch upstream
git merge upstream/main

Then re-run the automated upgrade (applies new schema patches, refreshes config, provisions only missing secrets, and redeploys):

npm run upgrade:remote

See Upgrades for details.

On this page