Kotauth, a self-hosted identity server built entirely on Ktor #5501
Anderson Fariña (InumanSoul)
started this conversation in
Show and tell
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
I've been building Kotauth, a self-hosted identity and access management server, and Ktor is the foundation of the entire thing. Now at v1.3.1 — wanted to share it here since the Ktor community might find some of the patterns interesting (or worth critiquing).
What it is: A multi-tenant auth server providing OAuth 2.0 / OpenID Connect, TOTP-based MFA, hierarchical RBAC, social login, webhooks, and a full admin console — all in a single Ktor application. MIT licensed.
The Ktor patterns worth looking at
Rather than listing features, here's what I think is interesting from a Ktor architecture perspective:
Hexagonal architecture with zero Ktor imports in the domain layer. Models, port interfaces, and business logic services have no framework dependency. Ktor route handlers are thin adapters that call domain services and map sealed
Resulttypes to HTTP responses. This means domain tests run in milliseconds with in-memory fakes — notestApplicationneeded.Route-scoped intercepts over application plugins. Instead of global plugins,
intercept(ApplicationCallPipeline.Call)resolves tenant context once per request intocall.attributes. Eliminated ~80 duplicate repository lookups across route files.Server-rendered UI with kotlinx.html — and a deliberately minimal frontend. A modern-looking UI doesn't need a client-side framework. The admin console, auth screens, and user portal are all kotlinx.html DSL backed by a BEM design system (~5,500 lines of CSS with custom properties for per-tenant theming), htmx for interactive actions (session revoke, user search, settings save — no full page reloads), and ~830 lines of vanilla JS total (password validation, MFA enrollment, toast notifications, confirm dialogs). CSS is compiled at build time by LightningCSS, JS is bundled by esbuild with SRI hashes — zero runtime Node.js. The result is auth screens that feel snappy, are fully white-label, and deploy as part of the same single JAR. No separate frontend build, no SPA hydration, no bundle size anxiety.
Full OAuth 2.0 / OIDC stack as plain Ktor routes. Discovery, JWKS, token, userinfo, introspection (RFC 7662), revocation (RFC 7009) — with per-tenant RS256 signing keys cached in a
ConcurrentHashMap.By the numbers
Kotlin 1.9.24, Ktor 2.3.12, Exposed 0.50.1, PostgreSQL 15. 29 Flyway migrations, 22 route files, 27 port interfaces with 24 corresponding fakes. Single JAR with Docker Compose quickstart.
I'd genuinely appreciate feedback from other Ktor developers — on the architecture, the patterns, the frontend approach, or anything that looks off. The codebase is open, take a look around.
All reactions