Skip to content
Public template

About

Self-hosted, open-source alternative to Auth0, built on Better Auth: OIDC provider, passkeys, SSO, organizations and an admin console.

Topics

Resources

Security policy

Stars

6 stars

Watchers

0 watching

Forks

Repository files navigation

Ostiary: one account for all your apps

Ostiary

A self-hosted, open-source alternative to Auth0, built on Better Auth.
One sign-in for all your apps: OAuth 2.1 and OpenID Connect provider, passkeys, enterprise SSO,
organizations and an admin console. Your users, your database, no per-user pricing.

Website · Live demo · Deploy · Connect an app · Docs

Deploy with Vercel

In the Middle Ages the ostiarius was the doorkeeper: the one who held the keys and decided who came in.

The Ostiary sign-in screen

Why

Hosted identity platforms are great until the bill scales with your users or you need your user data in your own database. Ostiary gives you the same building blocks as a deployable Next.js app you own:

  • Standard protocols. Any app that speaks OpenID Connect signs in with Ostiary: Next.js, Remix, mobile apps, CLIs, APIs.
  • Your data. Everything lives in your Postgres database. No vendor lock-in.
  • No per-user pricing. It costs what your hosting costs.
  • Readable code. A small TypeScript monorepo on top of Better Auth, not a black box.

Features

For your users

  • Email and password with verification, username sign-in, password reset
  • Passwordless sign-in with a 6-digit code sent by email (works across devices and inside OAuth sign-ins)
  • Optional captcha (Cloudflare Turnstile, hCaptcha or reCAPTCHA v2) on sign-up, password sign-in, password reset and sign-in codes
  • Passkeys (WebAuthn), plus a recent sign-in required to add one
  • Two-factor authentication: authenticator app (TOTP) and backup codes, with "trust this device"
  • Social sign-in with every Better Auth provider (Google, Apple, Microsoft, GitHub and 32 more), set up from the admin console, with brand buttons and connected accounts, plus Google One Tap
  • Enterprise SSO with OIDC or SAML 2.0 (Okta, Entra ID, Google Workspace, JumpCloud), with DNS domain verification
  • Account dashboard: profile, email change (approved from the current inbox), sessions, passkeys, two-factor authentication, connected accounts, connected apps (with their icons, permissions in plain words, when they were connected and last used), and Your data: export everything as JSON or delete the account
  • Several accounts in one browser (up to 5): switch from the account menu, or pick one when an app asks with prompt=select_account
  • 20 locales, light and dark themes

For your apps

  • OAuth 2.1 / OpenID Connect provider: discovery, PKCE, refresh tokens, consent, UserInfo, introspection, JWKS
  • Machine-to-machine tokens (client credentials) with per-client scopes
  • API keys for scripts: users (or organizations) create keys for one of your APIs and some of its scopes; your API verifies them with Ostiary
  • Self-registration for MCP clients and AI agents: Dynamic Client Registration and Client ID Metadata Documents, off by default and controlled from the admin console. Anonymous registration is limited to public PKCE clients (no secret leaves without a sign-in) — see MCP and AI agents
  • Device sign-in (RFC 8628) for CLIs, TVs and other apps without a browser
  • Protected resources: JWT access tokens scoped to your APIs, with the user's role as a claim
  • Organizations with members, roles and invitations
  • SCIM 2.0 provisioning per organization: Okta, Entra ID and other identity providers create and deactivate accounts

For you (admin console)

  • Users: search, roles, bans, sessions, impersonation, two-factor reset
  • Sign-in providers: turn social sign-in providers on and off, order them and paste their credentials (stored encrypted) without a redeploy
  • Sign-in branding per application: display name, logo, accent color (with WCAG contrast checks), tagline, side panel and which social buttons show, with a live preview
  • OAuth clients with their icons, an App usage page (tokens, users and consents per app over 30 days), consents, organizations, SSO providers
  • API keys: turn them on, set their maximum lifetime, see and revoke every key
  • Audit log of every admin action, sign-in activity and failed sign-in monitoring
  • Signing keys: automatic rotation on a schedule, or rotate now, with a grace period during which old tokens keep verifying
  • Rate limits per client IP on sign-in, codes, password reset and token endpoints, counted in Postgres so they hold on serverless

How it compares

Ostiary Auth0
Hosting Your Vercel account and Postgres Auth0 cloud
Pricing Your infrastructure Per monthly active user
OIDC / OAuth 2.1 provider Yes Yes
Passkeys, two-factor authentication, social sign-in, organizations Yes Yes
Enterprise SSO OIDC and SAML 2.0 OIDC and SAML
Admin console and audit log Yes Yes
SCIM provisioning, breached-password detection Yes Yes
Compliance certifications and SLA No Yes
Source code Yours, MIT Closed

Ostiary is a good fit when you want to own your identity layer. If you need a managed service with compliance certifications and an SLA, a hosted platform is the better choice.

Deploy

  1. Click Deploy with Vercel above. Vercel creates a Neon Postgres database for you and asks for:

    • BETTER_AUTH_SECRET: 32+ random characters (openssl rand -base64 32)
    • ADMIN_EMAILS: your email address, so your account becomes an admin when you sign up and verify it
    • RESEND_API_KEY and RESEND_FROM: from resend.com, to send verification emails
  2. The build applies the database migrations. When it finishes, open your deployment and sign up with the email you put in ADMIN_EMAILS, then open the verification link sent to it: the account becomes an admin once the address is verified. (Signing up with a social provider works too when the provider reports the address as verified; SSO never grants the admin role.) The admin console asks you to turn on two-factor authentication before you use it.

  3. Optional: deploy the admin console as a second project with the same database and secret:

    Deploy the admin console

    For a single sign-in across both apps, give them subdomains of one domain (for example auth.example.com and admin.example.com) and set COOKIE_DOMAIN=.example.com on both. Read COOKIE_DOMAIN first: the session cookie is then sent to every subdomain of that domain.

Connect an app

Ostiary is a standard OpenID Connect provider. Register a client in the admin console (Applications), then point your app at the discovery document:

https://<your-ostiary-domain>/api/auth/.well-known/openid-configuration

For example, with Auth.js in a Next.js app:

import NextAuth from "next-auth";

export const { handlers, auth, signIn, signOut } = NextAuth({
  providers: [
    {
      id: "ostiary",
      name: "Ostiary",
      type: "oidc",
      issuer: "https://auth.example.com/api/auth",
      clientId: process.env.OSTIARY_CLIENT_ID,
      clientSecret: process.env.OSTIARY_CLIENT_SECRET,
    },
  ],
});

Any OIDC library works the same way (Better Auth's generic OAuth, openid-client, AppAuth on mobile): give it the issuer, client ID and secret.

The full guide covers protecting your APIs, signing key rotation, device sign-in for CLIs and TVs, and branding the sign-in page per app.

Documentation

Guide What it covers
Connect an app OIDC setup, APIs and scopes, signing keys, device flow, per-app branding, Google One Tap
Social sign-in Turning on Google, Apple, GitHub and 33 more providers from the admin console
Enterprise SSO OIDC and SAML 2.0 identity providers (Okta, Entra ID, Google Workspace), domain verification
SCIM provisioning Okta and Entra ID creating and deactivating accounts per organization
Webhooks Events, Standard Webhooks signatures, retries and the delivery log
MCP and AI agents Dynamic Client Registration, Client ID Metadata Documents, protecting an MCP server
API keys Personal and organization keys for your APIs, and how your API verifies them
Your data Data export and account deletion (GDPR), what is kept and why
Configuration Every environment variable
Security Security model, rate limiting, client IP, COOKIE_DOMAIN
Testing Unit tests and the Playwright end-to-end suite

Run locally

Requirements: Node.js 20+, pnpm 11, a Postgres database.

pnpm install
cp apps/auth/.env.example apps/auth/.env.local     # fill in DATABASE_URL and BETTER_AUTH_SECRET
cp apps/admin/.env.example apps/admin/.env.local   # same DATABASE_URL and BETTER_AUTH_SECRET
pnpm db:migrate
pnpm dev:auth     # http://localhost:3000
pnpm dev:admin    # http://localhost:3001

Without Resend configured, development prints verification and reset links, and sign-in codes, to the console.

Architecture

apps/auth       Sign-in, sign-up, consent, OIDC endpoints, account dashboard
apps/admin      Admin console (optional): users, clients, organizations, SSO, audit
packages/core   Better Auth configuration, database schema and migrations, emails, UI, translations

Both apps run the same Better Auth configuration against one database. The admin app only exposes an allowlist of auth endpoints; sign-in and the OIDC protocol stay on the auth app.

In production

Cyber Auth, the single sign-on for the Cyber ecosystem (CyberCTF, Cyber Courses, Cyber Bench), runs on Ostiary.

Credits

Built on Better Auth (MIT). Ostiary is a community project and is not affiliated with Better Auth. Type: Instrument Sans and Instrument Serif and Geist Mono (SIL Open Font License).

License

MIT © Florian Amette

About

Self-hosted, open-source alternative to Auth0, built on Better Auth: OIDC provider, passkeys, SSO, organizations and an admin console.

Topics

Resources

Security policy

Stars

6 stars

Watchers

0 watching

Forks

Contributors

Languages