The Problem

Authgear solves the "build your own auth" trap: every SaaS product needs signup, login, MFA, SSO, and session management, yet implementing these correctly is security-sensitive and time-consuming. Rolling your own means owning OIDC/OAuth 2.0/SAML compliance, passkey protocols, brute-force protection, and audit logging — work that distracts from the product.

What This Does

Authgear is an open-source, self-hostable authentication server with a pre-built login UI (authui/), a GraphQL admin API (pkg/lib/admin/), and a management portal (portal/). It supports passwordless login (magic links, OTP), passkeys, biometric login, TOTP/SMS/email 2FA, OIDC/OAuth 2.0/SAML SSO, and enterprise features like RBAC, audit logs, and rate limiting.

The repository is a monorepo of 13 self-contained projects. The core server (pkg/, 2,664 files) is Go; the portal and auth UI are React/TypeScript. The cmd/authgear/ directory contains the entry point, and e2e/ holds end-to-end tests. It was forked from the 1,999-star authgear/authgear-server project.

How It Is Wired

Execution starts at cmd/authgear/main.go, which loads configuration and wires dependencies via wire.go / wire_gen.go (compile-time dependency injection). The server exposes three APIs: the public auth API, the admin GraphQL API (cmd/authgear/adminapi/), and the portal API. The admin API routes through pkg/lib/admin/graphql/, which resolves mutations and queries against the database and Redis.

The portal/ frontend (React + Tailwind) calls the admin GraphQL API to manage users, authentication flows, and tenant settings. The authui/ directory contains the pre-built login pages, styled with Tailwind and served by the Go server. The pkg/lib/authn/ package handles the actual authentication logic — passkeys, OTP, SSO — and writes sessions to Redis and user records to the database. The pkg/lib/oauth/ package implements the OIDC/OAuth 2.0 endpoints.

The widest blast radius sits in pkg/lib/authn/ and pkg/lib/oauth/: every authentication flow routes through these packages, and a change there affects all 13 projects. The module graph shows a hub around pkg/lib/ with cycles between authn, oauth, and session — modifying one often requires touching the others.

How To Use It

Setup: Build the Docker image from cmd/authgear/Dockerfile and run via docker compose. The Makefile has make build and make test targets.

Configuration: Copy .env.example to .env and set database and Redis connection strings. Secrets go in authgear.secrets.yaml (see hack/custom-resources/ for a template).

Running it:

docker build -f cmd/authgear/Dockerfile -t authgear .
docker run -p 3000:3000 -v $(pwd)/authgear.secrets.yaml:/app/authgear.secrets.yaml authgear

Real-World Use

A SaaS company self-hosts Authgear behind their API gateway. Users hit the pre-built login page (authui/), authenticate via passkey or OTP, and receive an OIDC token. The company's backend validates the token via the OIDC discovery endpoint, while the admin portal (portal/) manages users, enforces MFA, and reviews audit logs. The GraphQL admin API (pkg/lib/admin/graphql/) lets the company programmatically provision tenants and sync users with their CRM.

Code Health & Issues

Static analysis found 12 findings (0 critical, 3 high, 7 medium, 2 low):

  • Highe2e/.env is tracked despite .gitignore excluding it; credentials may be live. Fix: git rm --cached, rotate, keep ignore rule.
  • High – GitHub Actions use oursky/action-gh-release@v2 (tag-pinned). Fix: pin to commit SHA.
  • High – Committed .env in e2e/. Fix: remove, rotate, add .env.example.
  • Medium – 3 workflows declare no permissions for GITHUB_TOKEN. Fix: add contents: read.
  • Medium – No Dependabot/Renovate despite 10 manifests. Fix: add .github/dependabot.yml.
  • Medium – Base images (node:20.19.5-bookworm, quay.io/theauthgear/golang:1.26.2-noble) not digest-pinned. Fix: use image@sha256:<digest>.
  • Medium – No pre-commit secret gate. Fix: add hook scanning staged content.
  • Medium – Large blobs tracked: cldr-common-44.0.zip (30.3MB), GeoLite2-Country.mmdb (9.1MB). Fix: use Git LFS.
  • Mediumpersist-credentials: false not set on checkout in run-checks.yaml. Fix: add it.
  • Medium – No non-root USER in cmd/authgear/Dockerfile. Fix: add unprivileged user.

The Bottom Line

Authgear is a serious, production-grade authentication server with broad protocol support and a real admin portal — the Go core is well-structured and the test suite (961 files) is substantial. The committed secrets and unpinned CI actions are the main concerns; fix those before production. It's appropriate for teams needing a self-hosted Auth0/Clerk alternative with enterprise features and who can maintain a Go codebase.