← Back to archive

Repo of the Day

anomalyco/openauth

Published: Jan 14, 2025

Open repository ↗

▦ Universal, standards-based auth provider.

Summary

OpenAuth is a self-hosted, OAuth 2.0-based authentication server written in TypeScript that can run as a standalone service or be embedded into an existing application. It targets web apps, mobile apps, single-page apps, internal tools, and third-party clients, and is currently labeled as beta in the README. The library is built on the Hono web framework and ships with provider integrations, a themeable UI, and a small client SDK.

What it is useful for

OpenAuth is useful when you want a single, centralized auth server running on your own infrastructure instead of using a SaaS product or wiring auth into each application separately. It implements the OAuth 2.0 specification, so any OAuth-compatible client can use it, including third-party applications that need a "log in with myapp" flow.

It supports multiple identity sources: third-party providers such as GitHub, built-in flows such as email/password and pin code, or custom providers you implement yourself. The runtime is portable across Node.js, Bun, AWS Lambda, and Cloudflare Workers, and a minimal KV-style storage layer (with adapters for Cloudflare KV, DynamoDB, and an in-memory store for tests) holds refresh tokens and password hashes.

The project explicitly does not handle user management. Once a user is identified, OpenAuth invokes a callback where you look up or create the user record, so you can keep your existing database and ORM. A documented limitation is that OpenAuth is still in beta, and the README recommends the examples/ folder and SST components for fuller deployments.

How engineers can use it

The README documents the following quick-start path:

  1. Import issuer from @openauthjs/openauth and configure providers, subjects, storage, and a success callback. For example:

    import { issuer } from "@openauthjs/openauth"
    import { GithubProvider } from "@openauthjs/openauth/provider/github"
    import { PasswordProvider, PasswordUI } from "@openauthjs/openauth/provider/password"
    
    const app = issuer({
      providers: {
        github: GithubProvider({
          clientID: process.env.GITHUB_CLIENT_ID!,
          clientSecret: process.env.GITHUB_CLIENT_SECRET!,
          scopes: ["user:email"],
        }),
        password: PasswordProvider(PasswordUI({
          sendCode: async (email, code) => { console.log(email, code) },
        })),
      },
      subjects,
      storage: MemoryStorage(),
      async success(ctx, value) {
        // look up or create user, then return ctx.subject("user", { userID })
      },
    })
    
  2. Define subjects with valibot (or any Standard Schema-compatible library) so the JWT payload is typed.

  3. Export the Hono app for the chosen runtime: export default app for Bun or Cloudflare Workers, wrap with hono/aws-lambda's handle for Lambda, or @hono/node-server's serve for Node.js.

  4. On the client, use createClient from @openauthjs/openauth/client. For server-rendered apps, run the code flow via client.authorize(redirectUri, "code") and exchange the code with client.exchange. For SPAs and mobile apps, enable PKCE with { pkce: true }, store the verifier, then send the access token as Authorization: Bearer ... to your API. Verify with client.verify(subjects, accessToken, { refresh }), which auto-refreshes expired tokens.

For full production setup details, the README points to openauth.js.org.