teamhanko/hanko
Modern authentication, on your terms. Open source alternative to Auth0, Clerk, WorkOS, Stytch.
Single-maintainer risk — review before adopting
weakest axisnon-standard license (Other); no tests detected
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 1d ago
- ✓4 active contributors
- ✓Other licensed
Show all 8 evidence items →Show less
- ✓CI configured
- ⚠Small team — 4 contributors active in recent commits
- ⚠Single-maintainer risk — top contributor 86% of recent commits
- ⚠Non-standard license (Other) — review terms
- ⚠No test directory detected
What would change the summary?
- →Use as dependency Concerns → Mixed if: clarify license terms
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Forkable" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/teamhanko/hanko)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/teamhanko/hanko on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: teamhanko/hanko
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/teamhanko/hanko shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
WAIT — Single-maintainer risk — review before adopting
- Last commit 1d ago
- 4 active contributors
- Other licensed
- CI configured
- ⚠ Small team — 4 contributors active in recent commits
- ⚠ Single-maintainer risk — top contributor 86% of recent commits
- ⚠ Non-standard license (Other) — review terms
- ⚠ No test directory detected
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live teamhanko/hanko
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/teamhanko/hanko.
What it runs against: a local clone of teamhanko/hanko — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in teamhanko/hanko | Confirms the artifact applies here, not a fork |
| 2 | License is still Other | Catches relicense before you depend on it |
| 3 | Default branch main exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 31 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of teamhanko/hanko. If you don't
# have one yet, run these first:
#
# git clone https://github.com/teamhanko/hanko.git
# cd hanko
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of teamhanko/hanko and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "teamhanko/hanko(\\.git)?\\b" \\
&& ok "origin remote is teamhanko/hanko" \\
|| miss "origin remote is not teamhanko/hanko (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(Other)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"Other\"" package.json 2>/dev/null) \\
&& ok "license is Other" \\
|| miss "license drift — was Other at generation time"
# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
&& ok "default branch main exists" \\
|| miss "default branch main no longer exists"
# 4. Critical files exist
test -f "backend/cmd/root.go" \\
&& ok "backend/cmd/root.go" \\
|| miss "missing critical file: backend/cmd/root.go"
test -f "backend/config/config.go" \\
&& ok "backend/config/config.go" \\
|| miss "missing critical file: backend/config/config.go"
test -f "backend/cmd/serve/all.go" \\
&& ok "backend/cmd/serve/all.go" \\
|| miss "missing critical file: backend/cmd/serve/all.go"
test -f "backend/crypto/jwk/aws_kms/manager.go" \\
&& ok "backend/crypto/jwk/aws_kms/manager.go" \\
|| miss "missing critical file: backend/crypto/jwk/aws_kms/manager.go"
test -f "backend/audit_log/logger.go" \\
&& ok "backend/audit_log/logger.go" \\
|| miss "missing critical file: backend/audit_log/logger.go"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 31 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~1d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/teamhanko/hanko"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
Hanko is an open-source authentication and user management platform built in Go (1.3M LOC) that replaces Auth0, Clerk, and WorkOS. It provides passwordless authentication (passkeys, passcodes), traditional passwords, OAuth SSO, SAML enterprise integration, MFA (TOTP/security keys), and webhooks—all self-hostable or on Hanko Cloud. The backend is a REST API using Echo framework; the frontend is Hanko Elements (TypeScript web components) and a JavaScript SDK. Monorepo split into three main areas: backend/ (Go REST API with Echo, using Cobra for CLI commands under cmd/, audit logging, multiple DB drivers), frontend/ area (TypeScript SDK and web components), and workflow automation in .github/workflows/. The backend uses struct-based configuration via koanf (YAML/JSON), database agnostic ORM (Pop/Ent), and Redis for session/lock management.
👥Who it's for
Full-stack developers and DevOps engineers building SaaS or enterprise applications who want to self-host authentication without vendor lock-in, and teams evaluating open-source alternatives to proprietary auth platforms. Also relevant to compliance-focused organizations that need data minimalism and on-premises control.
🌱Maturity & risk
Production-ready. The project has substantial Go codebases (backend), TypeScript SDKs, established CI/CD pipelines (CodeQL, e2e tests, Docker publishing, release workflows), and structured GitHub workflows for multiple release channels (CLI, frontend SDK, Hanko Elements). The Go version (1.26.1) is current, and the breadth of implemented features (passwords, passkeys, OAuth, SAML, MFA, webhooks, sessions) indicates active mature development.
Moderate risk. The backend depends on 40+ external Go packages (AWS SDK, WebAuthn, Redis, multiple databases, SAML libs) which expands the attack surface, though core dependencies (go-webauthn, jackc/pgx, lestrrat-go/jwx) are well-maintained. Single monorepo houses backend + frontend + CLI, so breaking changes in shared APIs can cascade. No visible SLA or security incident history in the provided data, but self-hosting introduces operational burden (DB migrations, Redis setup, TLS management). Organizations lacking DevOps expertise should evaluate managed Hanko Cloud.
Active areas of work
Active multi-track development: CLI publishing, frontend SDK releases, Hanko Elements web component releases, schema generation/validation workflows, Docker image publishing, and e2e testing. The .github/workflows/ directory shows parallel CI tracks for Go tests, frontend builds, CodeQL analysis, and dependabot updates—indicating regular releases and security-conscious maintenance.
🚀Get running
Clone the repo, then navigate to backend and frontend separately:
git clone https://github.com/teamhanko/hanko.git
cd hanko/backend
go mod download
go run ./cmd/root.go serve
For frontend/TypeScript components, use npm (dependencies visible in package management workflows):
cd hanko/frontend
npm install
npm run dev
See backend/README.md and specific workflow files for database setup (PostgreSQL/MySQL default) and Redis for sessions.
Daily commands: Backend dev server:
cd backend
go run ./cmd/root.go serve
Requires environment config (see .editorconfig, likely via envconfig or koanf file). Frontend:
cd frontend # or whichever frontend dir exists
npm install
npm run dev
See .github/workflows/e2e.yml, go.yml, and build-frontend.yml for CI patterns and exact build steps.
🗺️Map of the codebase
backend/cmd/root.go— CLI entry point and root command initialization—every contributor must understand the command structurebackend/config/config.go— Core configuration loader; all feature flags, auth methods, and runtime settings flow from herebackend/cmd/serve/all.go— Server initialization for public API, admin API, and audit logging—the main runtime bootstrapbackend/crypto/jwk/aws_kms/manager.go— Cryptographic key management; critical for JWT signing and security-sensitive operationsbackend/audit_log/logger.go— Audit logging infrastructure; required for compliance and security event trackingbackend/cmd/user/importer.go— User import/export pipeline; handles data serialization and bulk user operationsbackend/config/config_webhook.go— Webhook configuration and event dispatch; essential for third-party integrations
🛠️How to make changes
Add a new authentication method (e.g., SAML, OIDC provider)
- Create configuration struct in
backend/config/config_third_party.gofor the new provider settings (backend/config/config_third_party.go) - Add environment variable bindings and validation in the config struct (
backend/config/config.go) - Implement provider-specific client initialization in a new
backend/crypto/orbackend/auth/subpackage (backend/config/config_service.go) - Wire the provider into the public API server initialization in
backend/cmd/serve/public.go(backend/cmd/serve/public.go) - Add integration tests using the test fixtures pattern in
backend/cmd/user/import_test.go(backend/cmd/user/import_test.go)
Add a new webhook event type
- Define the event type and payload schema in
backend/config/config_webhook.go(backend/config/config_webhook.go) - Add the event to the audit logger in
backend/audit_log/logger.goto ensure it's tracked (backend/audit_log/logger.go) - Emit the event from the relevant business logic (e.g., user creation, MFA enrollment) and call the webhook dispatcher (
backend/cmd/serve/public.go) - Test webhook delivery and retry logic using test fixtures in
backend/cmd/user/import_test.gopattern (backend/cmd/user/import_test.go)
Add a new admin CLI command
- Create a new file in
backend/cmd/following the pattern ofbackend/cmd/user/root.go(backend/cmd/user/root.go) - Define command flags and validate them using the config pattern from
backend/config/config.go(backend/config/config.go) - Register the command in
backend/cmd/root.gowith proper help text and subcommand structure (backend/cmd/root.go) - Add unit tests alongside the command file (e.g.,
command_test.go) matchingbackend/cmd/user/import_test.gopattern (backend/cmd/user/import_test.go)
Add support for a new database backend
- Extend
backend/config/config_database.goto include connection string and driver settings for the new database (backend/config/config_database.go) - Create database adapter logic following the pattern used by existing drivers (MySQL, PostgreSQL references in go.mod) (
backend/config/config.go) - Update migration files in
backend/cmd/migrate/to support the new database dialect (backend/cmd/migrate/up.go) - Test with the configuration loader in
backend/config/config_test.go(backend/config/config_test.go)
🪤Traps & gotchas
Database initialization required: Backend expects PostgreSQL, MySQL, or SQLite configured via environment; migrations must run before first startup (go run ./cmd/root.go migrate up). Redis dependency: Session storage and distributed locks require Redis; if not configured, session revocation and multi-instance deployments will fail silently. JWT/OIDC keys: backend/cmd/jwk/ tools must generate or import keys before auth endpoints work; missing keys cause startup or runtime failures. Configuration format: Config is YAML/JSON via koanf, not simple env vars; mismatched structure silently fails. Web component path issues: Frontend SDK and Hanko Elements have separate release channels in npm; version mismatches between SDK and elements can break integration. SAML certificate handling: SAML flows require valid certificates; no validation feedback if malformed. Database driver selection: Pop ORM auto-detects via URL scheme, but mixing drivers in migrations can cause schema drift.
🏗️Architecture
💡Concepts to learn
- FIDO2 / WebAuthn — Core to Hanko's passkey and security key support; understanding the challenge-response handshake and credential attestation is essential to grasping how Hanko achieves phishing resistance.
- SAML 2.0 Enterprise SSO — Hanko implements russellhaering/gosaml2 for enterprise federated auth; critical for organizations with existing IdPs like Okta or Azure AD.
- JWT (JSON Web Tokens) and JWK (JSON Web Key) — Hanko's API uses JWTs for stateless session tokens and lestrrat-go/jwx for key management; the
backend/cmd/jwt/andbackend/cmd/jwk/tools are essential for key rotation and token validation. - Distributed Session Management & Redis — Hanko uses go-redsync and redigo for Redis-backed sessions and distributed locks, enabling multi-instance deployments with session revocation; understanding key expiration and lock contention is critical for scaling.
- TOTP (Time-based One-Time Password) — Hanko's MFA implementation uses pquerna/otp for TOTP generation; understanding time window synchronization and secret encoding is needed to debug MFA flows.
- OAuth 2.0 Authorization Code Flow & OpenID Connect — Hanko integrates external OAuth providers (Apple, Google, GitHub) and acts as an OIDC provider itself; grasping redirect URIs, state tokens, and code-for-token exchange is foundational to social login features.
- Database Abstraction & ORM (Pop/Buffalo) — Backend uses gobuffalo/pop (v6.2.1) to abstract PostgreSQL/MySQL/SQLite; understanding Pop's migration DSL and query builder is essential for schema changes and data layer debugging.
🔗Related repos
ory/hydra— Open-source OAuth 2.0 and OpenID Connect provider; similar identity infrastructure but focused on delegation rather than passwordless UX.keycloak/keycloak— Enterprise-grade identity provider with SAML, OAuth, OIDC; competes directly with Hanko for self-hosted auth but heavier weight and Java-based.zitadel/zitadel— Go-based OIDC and OAuth provider emphasizing API-first design; closest direct competitor in the open-source auth space with similar target audience.passkeys-dev/passkeys.dev— Community resource documenting passkey/WebAuthn standards and integration patterns; useful reference for understanding the passkey features Hanko implements.duo-labs/py_webauthn— Python WebAuthn library (counterpart to go-webauthn used in Hanko backend); helps understand how Hanko's passkey validation logic aligns with FIDO2 specs.
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive end-to-end tests for SAML/OIDC flows in backend
The repo imports SAML and OIDC libraries (github.com/russellhaering/gosaml2, github.com/coreos/go-oidc/v3) and has mocking infrastructure (github.com/h2non/gock), but the e2e.yml workflow doesn't explicitly test these critical authentication flows. New contributors could add integration tests covering SAML assertion validation and OIDC provider federation to prevent authentication bypass vulnerabilities.
- [ ] Review backend/cmd/saml/saml.go and identify untested code paths
- [ ] Add test fixtures in backend/cmd/saml/ using go-testfixtures/v3 pattern already in use
- [ ] Create new test file backend/cmd/saml/saml_integration_test.go with gock-mocked provider responses
- [ ] Add OIDC federation tests following the same pattern
- [ ] Update .github/workflows/e2e.yml to run these backend integration tests
Add database migration validation tests for schema consistency
The repo has a migrations system (backend/cmd/migrate/) and uses gobuffalo/pop/v6 for ORM, but there are no apparent tests validating that migrations correctly map to Go struct definitions in backend/cmd/user/, backend/audit_log/, etc. This is critical for preventing data corruption. Contributors could add tests that verify schema-to-struct alignment.
- [ ] Create backend/cmd/migrate/migrate_test.go with testfixtures container setup using ory/dockertest/v3
- [ ] Add test to validate each migration generates expected schema against backend/config/config.go database definitions
- [ ] Test forward and backward migration idempotency using existing go-testfixtures approach
- [ ] Add schema validation helpers to catch struct field/database column mismatches early
- [ ] Integrate into .github/workflows/go.yml test suite
Add OpenAPI/Swagger generation and validation for backend API routes
The repo has structured API routes (backend/cmd/serve/public.go, admin.go) but lacks API documentation generation. Given the presence of invopop/jsonschema and existing schema generation (backend/cmd/schema/), contributors could implement OpenAPI spec generation from Echo route definitions and add validation to CI to catch API contract breaks.
- [ ] Create backend/cmd/schema/openapi.go to walk Echo router and generate OpenAPI 3.0.0 spec from route handlers
- [ ] Add JSON schema references for request/response types using existing invopop/jsonschema patterns
- [ ] Create backend/openapi_test.go to validate generated spec against actual HTTP responses
- [ ] Add new GitHub workflow .github/workflows/openapi-validate.yml to detect breaking changes
- [ ] Update CONTRIBUTING.md with API documentation requirements for new endpoints
🌿Good first issues
- Add missing test coverage for
backend/audit_log/logger.goandbackend/build_info/build_info.go—these files have no visible test siblings and are critical for compliance and release integrity. - Improve documentation for the koanf-based configuration system in
backend/cmd/schema/—generate a schema reference guide fromgenerate_config.gooutput and document all required/optional fields for self-hosted deployments. - Add health check and readiness probe examples to
backend/cmd/isready/isready.go—create Docker health check templates and Kubernetes probe manifests to help operators deploy Hanko reliably.
⭐Top contributors
Click to expand
Top contributors
- @dependabot[bot] — 86 commits
- @lfleischmann — 10 commits
- @FreddyDevelop — 3 commits
- @jaffarkeikei — 1 commits
📝Recent commits
Click to expand
Recent commits
24fcc53— chore(deps): bump github.com/aws/aws-sdk-go-v2/config in /backend (#2618) (dependabot[bot])d605397— chore(deps-dev): bump webpack from 5.105.4 to 5.106.1 in /frontend (#2610) (dependabot[bot])6479f48— chore(deps): bump golang.org/x/crypto from 0.49.0 to 0.50.0 in /backend (#2599) (dependabot[bot])563a8c1— chore(deps): bump golang.org/x/text from 0.35.0 to 0.36.0 in /backend (#2600) (dependabot[bot])e6e54a3— chore(deps): bump react-router-dom from 7.13.1 to 7.14.0 in /frontend (#2604) (dependabot[bot])5791b8c— chore(deps): bump next from 16.2.2 to 16.2.3 in /frontend (#2602) (dependabot[bot])0e4a3b8— chore(deps): bump github.com/coreos/go-oidc/v3 in /backend (#2592) (dependabot[bot])e13c0ce— chore(deps-dev): bump ts-jest from 29.4.6 to 29.4.9 in /frontend (#2594) (dependabot[bot])079ea07— chore(deps-dev): bump ts-loader from 9.5.4 to 9.5.7 in /frontend (#2596) (dependabot[bot])c54b743— chore(deps-dev): bump sass from 1.98.0 to 1.99.0 in /frontend (#2597) (dependabot[bot])
🔒Security observations
Failed to generate security analysis.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.