No description
  • Go 96.5%
  • Go Template 1.8%
  • CSS 1.6%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Josh Quinlan 09e4b3de70
feat(oidc): serve the provider end to end
Discovery, the JWKS, authorisation with mandatory PKCE, the token
endpoint's code, refresh and client-credentials grants, consent, and
userinfo. burh now signs applications in, which is the point of it.

The front channel lives with the hosted pages, which own sessions and
templates; the back channel is pure protocol. Validation proves the
client and its redirect before anything else, because until then a
failure must not be delivered anywhere: sending an error onwards
would hand it to whatever address the request invented. Only once the
destination is proved may later failures travel by redirect.

The consent page asks in plain words and remembers the answer per
scope set; one new scope reopens the whole question. Trusted
first-party clients skip it. A denied person gets a page naming the
audit reference, so an administrator can find the exact moment.

The default signing key is minted at start-up rather than at first
sign-in, because relying parties fetch the JWKS when they are
configured, which is before anyone has signed in.

A replayed code ends the session it was bound to, and only that one:
the first redemption's winnings die with the session at their next
refresh, while ending every session would let a replayed code sign
the person out of everything, a denial of service rather than a
defence. The whole cascade is proved over live HTTP, replay to
refusal to the untouched browser session.
2026-08-28 18:54:47 +01:00
cmd/burh-server feat(server): enrol the first administrator and serve the API 2026-08-28 00:36:03 +01:00
internal feat(oidc): serve the provider end to end 2026-08-28 18:54:47 +01:00
.gitignore feat(server): lay the foundations for the identity provider 2026-08-27 23:07:55 +01:00
.golangci.yml feat(oidc): serve the provider end to end 2026-08-28 18:54:47 +01:00
.goreleaser.yaml feat(server): lay the foundations for the identity provider 2026-08-27 23:07:55 +01:00
go.mod feat(keys): sign tokens with sealed, rotating keys 2026-08-28 18:37:37 +01:00
go.sum feat(keys): sign tokens with sealed, rotating keys 2026-08-28 18:37:37 +01:00
LICENSE feat(server): lay the foundations for the identity provider 2026-08-27 23:07:55 +01:00
Makefile feat(server): lay the foundations for the identity provider 2026-08-27 23:07:55 +01:00
README.md feat(server): lay the foundations for the identity provider 2026-08-27 23:07:55 +01:00

burh-server

burh is a small, self-contained identity provider. One static Go binary holds the OpenID Connect provider, the hosted login pages, the administration API and its own replicated store, so a homelab runs it from a single container and a business runs the same build clustered across three nodes.

There is no external database, no message broker and no JavaScript build chain to operate. Point a reverse proxy at it, or let it terminate TLS itself, and it works.

Status

Early development. The foundations are in place; the store, the directory API and the OpenID Connect provider are being built in that order. Nothing here is ready to hold real accounts yet.

What it does

  • OpenID Connect and OAuth 2.0: authorisation code with PKCE, refresh with rotation and reuse detection, client credentials, the device flow, token exchange and dynamic client registration.
  • Credentials: passwords hashed with Argon2id, TOTP, and passkeys usable as a passwordless first factor. Magic links exist for resets, invitations and address verification only; they never bypass a login.
  • Directory: users, flat groups and administrator-defined typed attributes that can be mapped into token claims.
  • Access control: each client is open to everyone or restricted to named groups, optionally demanding multi-factor authentication.
  • Auditing: an append-only trail of every authentication decision and administrative change, queryable over the API, streamed live over server-sent events, and delivered to signed webhooks.
  • Operations: Prometheus metrics, OpenTelemetry traces, health and readiness endpoints, consistent snapshots, and optional built-in ACME certificates.
Repository Purpose
burhctl Terminal administration console and scriptable client
burh-self-service Reference self-service portal
burhlib The API description and its generated Go client

Building

Go 1.26 or newer is required.

make build      # bin/burh-server
make check      # lint and tests
make test

Linting uses golangci-lint and releases are cut with GoReleaser; both are expected on PATH. The version string comes from the git tag at build time and is not recorded anywhere in the source.

Releases

Tagged releases publish signed checksums alongside binaries for Linux, macOS and FreeBSD on amd64 and arm64:

make snapshot   # local build, no publishing

Release signing expects GPG_FINGERPRINT in the environment.

Contributing

Patches are welcome. Please keep to the conventions already in the tree: guard clauses over nested conditionals, files well under 500 lines, lines wrapped at 72 columns, and behaviour landing with a test. Commit messages follow Conventional Commits.

Licence

Apache-2.0. See LICENSE.