Quick Use
npm install @openauthjs/openauth- Author
issuer({providers, success})and deploy to Lambda / Vercel Functions - Client app uses
createClient().authorize(...)for OAuth flow
Intro
OpenAuth is a centralized auth server from Dax Raad's team (SST / Toolbeam) — self-host one OpenAuth server that issues OAuth-compatible tokens to all your apps, no matter what auth method (password, OAuth provider, SAML, passkey, magic link). Standards-based, multi-tenant, zero-vendor-lock-in alternative to Auth0/Clerk. Best for: side projects scaling to multiple apps, teams burned by Auth0 pricing tiers, anyone wanting full control over the user database. Works with: any web framework — TS, Python, Go, Rust, PHP. Setup time: 15 minutes.
Server (TypeScript example)
import { issuer } from "@openauthjs/openauth";
import { PasswordProvider } from "@openauthjs/openauth/provider/password";
import { GithubProvider } from "@openauthjs/openauth/provider/github";
import { CodeUI } from "@openauthjs/openauth/ui/code";
import { PasswordUI } from "@openauthjs/openauth/ui/password";
const auth = issuer({
storage: { type: "dynamo", table: "openauth" },
providers: {
password: PasswordProvider(PasswordUI({ /* email + password UI */ })),
github: GithubProvider({
clientID: process.env.GITHUB_CLIENT_ID!,
clientSecret: process.env.GITHUB_CLIENT_SECRET!,
scopes: ["user:email"],
}),
},
success: async (ctx, value) => {
return ctx.subject("user", {
id: value.email || value.clientID + ":" + value.id,
});
},
});
export const handler = auth.handler; // mount on AWS Lambda / Vercel FunctionsClient app (any framework)
import { createClient } from "@openauthjs/openauth/client";
const client = createClient({
clientID: "my-app",
issuer: "https://auth.example.com",
});
// Redirect to login
window.location.href = await client.authorize(
"https://my-app.com/callback",
"code"
);
// On callback
const tokens = await client.exchange(code, "https://my-app.com/callback");
// tokens.access, tokens.refresh — standard OAuth, use anywhereWhy OpenAuth vs Auth0/Clerk
| Need | OpenAuth | Auth0 | Clerk |
|---|---|---|---|
| Self-host | Yes | No (Private Cloud add-on $$$) | No |
| Pricing | Free (your infra) | $-$$$$ per MAU | Per MAU |
| Multi-tenant | Built-in | Yes | Yes |
| Standards-based | OAuth/OIDC native | OAuth/OIDC | Proprietary + OIDC |
| Storage | Postgres / DynamoDB / Cloudflare KV | Theirs | Theirs |
| Lock-in | None (your DB) | Vendor | Vendor |
Production checklist
- HTTPS only (issuer redirects break on HTTP)
- Rotate signing keys every 90 days (
auth.rotate()) - Set short-lived access tokens (15 min) + long refresh (30 days)
- Use Cloudflare KV or DynamoDB for global edge latency
FAQ
Q: Is it production-ready? A: Yes — Toolbeam runs it in production, several Anthropic-adjacent projects use it. Still v1.x so breaking changes possible. Pin a version and test upgrades.
Q: Storage options? A: Built-in adapters for DynamoDB (recommended for AWS-native), Cloudflare KV (edge-friendly), Postgres (self-host shops), and in-memory for tests. Custom adapter is a ~50-line file.
Q: How does it compare to Lucia / NextAuth? A: Lucia/NextAuth are libraries embedded in your app. OpenAuth is a separate centralized server — preferred when you have 3+ apps sharing users. For one app, NextAuth is simpler. For an org with many apps, OpenAuth is the cleaner architecture.
Source & Thanks
Built by Toolbeam (Dax Raad's team). Licensed under MIT.
toolbeam/openauth — ⭐ 2,800+