# Authgear Server: a self-hosted Auth0 alternative with passkeys and SSO

> Authgear is a Go-based identity provider that ships pre-built login and account settings pages, passkeys, MFA and SAML SSO. It is Apache-2.0 and can be self-hosted or run on Authgear Cloud; the trade-off is a multi-service stack to operate.

**authgear/authgear-server** — Open source Auth0/Clerk/Firebase alternative. Passkeys, SSO, MFA, passwordless, biometric login. Self-hosted or cloud. Enterprise-ready for SaaS & mobile apps

- Repository: https://github.com/authgear/authgear-server
- Website: https://www.authgear.com
- Stars: 2,086 · Forks: 127
- Language: Go
- License: Apache-2.0
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/authgear-authgear-server

## What Authgear Server actually replaces

Authgear Server is a full identity provider, not a library you link into an existing service. The README describes it as an "open-source extensible turnkey solution for all of your consumer authentication needs" and positions it against Auth0, Clerk and Firebase Auth. The target reader is a team building a SaaS product or a multi-app ecosystem that would otherwise pay a hosted identity vendor, and that wants the login flow, the account settings screen and the admin portal to exist before writing any frontend code.

The scope is wider than a typical OIDC server. The README lists passwordless login by magic link or OTP over email, SMS and WhatsApp; passkeys; biometric login on iOS and Android; TOTP with Google Authenticator or Authy; SMS and email second factors; social connections to Google, Facebook, Apple, WeChat and LinkedIn; SAML enterprise SSO; ADFS and LDAP connections; RBAC with roles and groups; and audit logs, brute-force protection, bot protection and rate limits. A team that only needs to validate JWTs against a public key is not the audience. A team that needs a signup page, a password reset flow and a support-facing user management screen is.

The repository is a Go monorepo. The module path is github.com/authgear/authgear-server and the go.mod declares Go 1.26.6. The top-level layout separates the server (cmd/, pkg/), the two frontends (authui/, portal/), database assets (postgres/, pgbouncer.ini, postgresql.conf), and observability configs (grafana-datasources.yaml, loki-config.yaml, otelcol-config.yaml, tempo-config.yaml). That layout tells you the intended deployment shape before you read a single doc page.

## How the pieces fit: Postgres, PgBouncer, Redis and a config source

The docker-compose.yaml at the repository root defines the local stack. There is a postgres16 service built from ./postgres/postgres16, with POSTGRES_USER and POSTGRES_PASSWORD both set to postgres. It publishes port 6432 on the host, and the comment in the file explains why: if you connect with psql or a GUI client you should use 6432, otherwise the client consumes the connection count.

In front of it sits pgbouncer, using the image edoburu/pgbouncer:v1.24.1-p1, publishing port 5432 and reading ./pgbouncer.ini and ./pgbouncer-users.txt. Applications are expected to talk to PgBouncer, not to the database directly. A redis service uses the image redis:6.0.20, and the comment notes that Azure Cache for Redis supports 6.0 only, which is the reason for the older tag.

The .env.example shows three separate Postgres URLs: DATABASE_URL, SEARCH_DATABASE_URL and AUDIT_DATABASE_URL, each with its own schema variable. Search and audit data are separated from the main application data at the connection level. The same file sets REDIS_URL and a distinct ANALYTIC_REDIS_URL on database 1, with ANALYTIC_ENABLED=true and an ANALYTIC_EPOCH of 2021-03-25. Elasticsearch is configured through ELASTICSEARCH_URL, and PostHog through ANALYTIC_POSTHOG_ENDPOINT and ANALYTIC_POSTHOG_APIKEY, both empty by default.

Configuration itself is pluggable. CONFIG_SOURCE_TYPE is set to local_fs with CONFIG_SOURCE_DIRECTORY=./var, and a commented block shows the alternative: CONFIG_SOURCE_TYPE=database. The .env.example also comments that one database connection is dedicated to LISTEN for config source changes, and that DATABASE_CONFIG_MAX_OPEN_CONN and DATABASE_CONFIG_MAX_IDLE_CONN are deliberately set to 2 to make a potential deadlock visible. That is an unusually candid note in a sample env file, and it tells you the database-backed config source relies on Postgres notifications.

## Installing Authgear Server from the repository

The Makefile is the entry point. The setup target depends on vendor, and vendor installs golangci-lint, runs go mod download, and then builds the frontends. The frontends are separate npm projects: build-frontend runs npm --prefix ./scripts/npm ci, npm --prefix ./authui ci and npm --prefix ./portal ci before the authui and portal targets. You need Go and Node available before setup will finish.

```bash
make setup
```

After that, the development stack comes up through the compose file. The postgres16 service listens on host port 6432 and PgBouncer on 5432, so check both before starting the server.

```bash
docker compose up -d
```

The .env.example is the template for runtime configuration. Copy it and adjust the endpoint and client identifiers; AUTHGEAR_ENDPOINT points at http://localhost:3100, and AUTHGEAR_APP_ID and AUTHGEAR_CLIENT_ID are set to accounts and portal for the local portal.

```bash
cp .env.example .env
```

With the stack running, the Makefile offers start, start-portal, and the once variants. The authgearonce-start target adds the authgearonce build tag, and authgearonce-start-portal does the same for the portal. The README also points at a hosted demo at demo.authgear.com if you would rather see the pre-built screens before running anything locally.

The API surface is documented in the repository. The siteadmin-api-docs target runs swaggerapi/swagger-ui on port 8101, mounting ./docs/api and setting SWAGGER_JSON to /api/siteadmin-api.yaml with OAUTH_USE_PKCE=true. The .env.example matches that port: CORS_ALLOWED_ORIGINS is localhost:8000,localhost:8101, with the comment that 8101 is the Swagger UI for the site admin API.

## Where Authgear Server is the wrong choice

The operational surface is the first limitation. A working local deployment needs Postgres, PgBouncer, Redis and the Go server, and the .env.example adds Elasticsearch and a second Redis database for analytics. That is a lot of moving parts for a product whose login page might serve a few thousand users. A single-binary identity provider or a managed service will be cheaper to run at that scale.

Configuration source is the second. The default in .env.example is local_fs, reading from ./var. The database-backed alternative is commented out, and the file warns that one connection is reserved for LISTEN. If you run several replicas against a database config source, you are depending on Postgres notification delivery for config propagation, and the sample file's own comment about deadlocks with a pool size of 2 suggests this path deserves testing before production.

The feature list also has gaps that matter. The README marks adaptive MFA as "coming soon", so risk-based step-up is not something you can configure today. And although the README advertises enterprise connections through ADFS and LDAP alongside SAML SSO, the repository files provided here do not document the exact configuration keys for those connections, so budget time in the docs before promising an enterprise customer a specific directory integration.

Finally, the licence is Apache-2.0, which is permissive, but the README also promotes Authgear Cloud and a scheduled demo. If your organisation needs a vendor support contract rather than community channels, the open source repository is not the thing you are buying.

## Authgear Server compared with Keycloak

Keycloak is the obvious alternative and the topics list on the repository names it explicitly. Both are self-hostable OIDC providers with SAML support, social login and MFA. The difference is in what ships in the box and what you build.

Keycloak is a Java application that has historically run as a single service with its own admin console, and it expects you to supply or theme the login pages yourself. Authgear Server instead ships authui and portal as first-class npm projects inside the same repository, and the Makefile builds them as part of setup. The README's pitch is a pre-built signup and login page with dark and light modes plus a pre-built account settings component, so the default path is closer to a finished consumer login experience.

Authgear also exposes a GraphQL Admin API, and the Makefile's siteadmin-api-docs target publishes a Swagger UI for the site admin API from docs/api/siteadmin-api.yaml. The README describes webhooks and TypeScript hooks for reacting to events such as a new signup, with custom logic. That extensibility model is a different answer to the same problem Keycloak solves with Java SPI implementations: you write a hook rather than a provider JAR.

The trade-off runs the other way too. Keycloak's single-service deployment is simpler than Authgear's Postgres plus PgBouncer plus Redis stack, and Keycloak's Java ecosystem means a larger pool of engineers who have already operated it. If your team is Go and Node, Authgear fits the existing toolchain; if your team is Java, the calculation changes.

## Maintenance, releases and the cost of upgrading

The repository is not archived, and the last push was on 2026-09-10. Releases arrive on a fortnightly cadence: 2026-08-12.0, 2026-08-26.0 and 2026-09-09.0, published on 2026-08-12, 2026-08-26 and 2026-09-09 respectively. Version numbers encode the release date, which makes it easy to see how far behind a deployment has fallen.

That cadence is the main maintenance cost. A fortnightly release train means upgrade work is a recurring task, not a yearly project. The go.mod pins Go 1.26.6, and the Makefile's vendor target installs a specific golangci-lint version, so build tooling moves with the repository. There are separate make targets for go-mod-tidy across every go.mod in the tree and for ensure-important-modules-up-to-date, which suggests dependency currency is treated as ongoing work rather than a one-off.

The database layer adds its own upgrade risk. Postgres runs behind PgBouncer, and the compose file notes that TLS for Postgres, PgBouncer and Redis is present but commented out. Enabling TLS means editing the compose mounts and the PgBouncer configuration together. The repository also carries pgbouncer.ini and postgresql.conf as tracked files, so those are configuration you own and must diff on upgrade.

On licensing, the repository ships LICENSE.txt and the project is Apache-2.0. That permits commercial use and modification, and it does not require you to publish your own changes. It also means there is no copyleft obligation on the surrounding application. This is a description of the licence identifier, not legal advice; if you are embedding Authgear in a distributed product, have your own counsel read LICENSE.txt.

## Conclusion

Adopt Authgear Server if you want an OIDC provider you control with passkeys, MFA and SAML SSO already built, and you are willing to run Postgres, PgBouncer and Redis. Do not adopt it if you only need a token endpoint for a single internal service, or if nobody on the team can operate a multi-container Go deployment. Before committing, read the .env.example and docker-compose.yaml at the repository root, confirm the CONFIG_SOURCE_TYPE setting you intend to use, and check whether the portal and authui frontends are built by make setup in your environment.

## FAQ

### What is an auth server?

It is the service that handles signup, login, sessions and token issuance for your applications. Authgear Server fills that role by acting as an OIDC/OAuth 2.0 and SAML provider with pre-built login, account settings and admin screens.

### Is Auth0 safe to use?

The repository does not evaluate Auth0. It presents Authgear Server as an open source alternative to Auth0, Clerk and Firebase Auth, and the reason to pick it is that you can self-host the identity data instead of relying on a third party.

### What does auth service mean?

In this context it means the component that authenticates users and issues credentials to your apps. Authgear Server covers that plus authorization through roles and groups, and it exposes a GraphQL Admin API for managing users.

### What is auth used for?

It is used to establish who a user is before your application grants access to data or actions. Authgear Server supports this with passwords, passkeys, biometric login, magic links and OTP, plus MFA for a second factor.

## Sources

- [authgear/authgear-server on GitHub](https://github.com/authgear/authgear-server)
- [License: Apache-2.0](https://github.com/authgear/authgear-server/blob/main/LICENSE)
- [Project website](https://www.authgear.com)
- [README](https://github.com/authgear/authgear-server/blob/main/README.md)
- [Releases](https://github.com/authgear/authgear-server/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/authgear-authgear-server
