mini-auth

A family of small, single-responsibility auth & identity services you can actually read. Educational, but homelab-functional — real crypto, heavily commented, and built to teach how authentication and authorization actually work.

Java 21 OAuth 2.0 OpenID Connect WebAuthn / passkeys mTLS JOSE / JWT MIT License

What is mini-auth?

mini-auth is a monorepo for a family of small auth/identity pieces. Each "mini" is either a library (focused machinery — a token plane, a policy decision function) or a service (a thin deployable front door — an OpenID Provider, a forward-auth gateway, an internal CA). They compose into a working self-hosted auth stack, and one ./gradlew build compiles and tests the whole family.

The crypto is real and built on vetted constructions (Ed25519, AES-256-GCM, Argon2id, PKCE, WebAuthn) — but the project is educational and explicitly not audited. The point is that the code is meant to be read, and that each service demonstrates a security principle in isolation.

Auth as a black box

  • Identity providers are opaque — you configure them, never see how they work
  • "JWT" is a string you copy around without understanding what's signed
  • Properties like no-oracle, constant-time compare, deny-by-default stay invisible
  • Learning means wading through huge, production-hardened codebases

mini-auth

  • Every service is small and heavily commented — written to be read
  • Build and verify a token by hand, then flip one byte and watch it fail
  • Each mini isolates one principle: envelope encryption, forward-auth trust, …
  • Runs a real self-hosted SSO + gateway + CA on your homelab

The family at a glance

Seven deployable services and the shared libraries all ship and run — including mini-console, the admin console + exercise harness over the whole family (reached through a set of thin per-service client libraries). pk-auth is an external passkeys library, embedded by mini-oidc.

Component Role Type Status
mini-kms Envelope-encryption KMS — the vault that wraps other services' signing keys. service shipping
mini-idp Machine identity — OAuth2 client-credentials → Ed25519 JWT + JWKS. service shipping
mini-oidc Human SSO / OpenID Provider — auth-code + PKCE, passkeys (embeds pk-auth). service shipping
mini-gateway Forward-auth endpoint for a reverse proxy (Traefik / Caddy / nginx). service shipping
mini-directory Identity source of truth — humans, service accounts, groups, roles, grants. service shipping
mini-ca Internal CA for mTLS / workload identity — CA key wrapped under mini-kms. service shipping
mini-token Shared token plane — JWS, JWKS, rotation, revocation, audit, SSO sessions. library shipping
mini-policy One decide(principal, action, resource) → allow/deny engine. library shipping
mini-console Optional unified admin console + exercise harness over the family — adds no new authority. service shipping

How it fits together

The names alone don't reveal the runtime relationships. Both issuers mint through one token plane; everything decides through one policy engine; and the keys that sign tokens are themselves wrapped by the KMS — the recursive integration.

Runtime relationships

   Humans (browser)                      Services / workloads
        │                                       │
        ▼                                       ▼
   ┌───────────┐                           ┌───────────┐
   │ mini-oidc │  human SSO (PKCE,         │ mini-idp  │  machine tokens
   │           │  passkeys via pk-auth)    │           │  (client-credentials)
   └─────┬─────┘                           └─────┬─────┘
         │     both resolve identities from      │
         │     mini-directory, mint through ─────┤
         ▼                                       ▼
   ╔═══════════════════════════════════════════════════╗
   ║  mini-token   —  JWS · JWKS · rotation · sessions ║
   ╚════════════════════════┬══════════════════════════╝
                            │  signing keys wrapped by
                            ▼
                      ┌───────────┐
                      │ mini-kms  │  envelope encryption / KMS
                      └───────────┘   (also wraps mini-ca's CA key)

   mini-directory  — the identity source of truth (issuers resolve here)
   mini-policy     — one decide(principal, action, resource) for every service
   mini-gateway    — forward-auth: reuses mini-token sessions + mini-policy routes

mini-directory is the source of truth: mini-idp reads its service accounts from it on every token request, and mini-oidc resolves humans from it. mini-gateway reads the very same SSO session mini-oidc writes — there is one session mechanism in the family, not two. Read the full map in DIRECTION.md.

Learn authentication & authorization

mini-auth doubles as a course. The docs teach the principles using the family as the worked example — and every concept ends with a pointer into the shipping code. Two complementary on-ramps: concepts-first (TEACHING.md) or code-first (LEARNING.md).

Concepts, built from zero

authn vs authz, what a token is, sessions vs tokens, OAuth/OIDC flows, envelope encryption, the authorization model, and the family's secure-design reflexes.

Hands-on labs

Predict-then-run tutorials. The keystone: build and verify an Ed25519 token by hand, then flip one byte and watch verification fail.

A security track

A threat-model overview plus per-service findings written as issue → attack → defense → test — teaching threat modeling as a method, not a checklist.

Honest seams

The docs name every path that is designed but not yet wired, so a lab never sends you to trace something through code that the code doesn't actually do.

Documentation

This site is the entry point; the docs themselves live in the repository.

Quick start

JDK 21+ on your PATH. One root wrapper builds and tests the whole family.

Run the family
Build & test
Learn by reading
# bring the family up in dependency order (loopback only), tear down on Ctrl-C
git clone https://github.com/codeheadsystems/mini-auth.git
cd mini-auth

docs/examples/run-family.sh              # directory + idp + oidc + gateway
docs/examples/run-family.sh --with-kms   # also mini-kms, signing keys wrapped

It builds the launchers, generates demo secrets, binds everything to 127.0.0.1, and prints each service's /docs URL. See run-the-whole-family.md.

./gradlew build        # compile + test EVERYTHING — this IS the CI gate
./gradlew test         # tests only, all modules
./gradlew :services:mini-oidc:installDist   # a runnable launcher

One toolchain (JDK 21), one version catalog, one set of convention plugins. No separate linter — ./gradlew build is the full gate.

# concepts-first — the course
open docs/TEACHING.md

# or code-first — walk the source in dependency order
open docs/LEARNING.md

# the keystone lab: build and verify a token by hand
open docs/tutorials/02-build-and-verify-a-token-by-hand.md

Keep GLOSSARY.md open for vocabulary, and read honest-seams.md before any deep dive.