A complete app with auth in one static Go binary and one SQLite file: no database server, no cgo, no framework.
storage/sqlite(pure Go,modernc.org/sqlite) holds users, sessions and tokens.- Stdlib
net/httpmux:/auth/isa.Handler(). - First-run setup token: the first admin can only sign up with the token, then signup closes.
GET /api/whoamiis guarded byRequireAbility("read")and accepts a session cookie or a bearer token.- Scoped API tokens are minted through the built-in
POST /auth/tokens. cmd/myclisigns in with the RFC 8628 device grant (clientauth.DeviceLogin), then callsWhoami,Logoutand the API.GET /deviceis a tiny approval page for the device flow.
Go 1.26 or newer. storage/sqlite and its modernc.org/sqlite dependency declare go 1.26.0, so this example does too. The root theauth-go module still builds on Go 1.25.
cd examples/single-binary-sqlite
SETUP_TOKEN=change-me go run .Without SETUP_TOKEN a random one is generated and logged once at startup. Environment: BASE_URL (default http://localhost:8080), ADDR (:8080), DB_PATH (app.db).
Create the first admin, mint a token, call the API:
curl -c jar -X POST localhost:8080/auth/email-password/signup \
-H 'X-Setup-Token: change-me' -H 'Content-Type: application/json' \
-d '{"email":"admin@example.com","password":"correct horse battery staple"}'
curl -b jar -X POST localhost:8080/auth/tokens -H 'Content-Type: application/json' \
-d '{"name":"ci","abilities":["read"]}' # prints the token once
curl -H "Authorization: Bearer $TOKEN" localhost:8080/api/whoamiSign a CLI in with the device grant:
go build -o mycli ./cmd/mycli
export MYCLI_SERVER=http://localhost:8080
./mycli login # prints a code; approve it at http://localhost:8080/device
./mycli whoami
./mycli get /api/whoami
./mycli logout # revokes the token server side and deletes it locallySignup, signin and token routes share a per-IP budget of 5 requests a minute by default (Config.RateLimitPerIP).
go vet ./... && go test ./...TestSmoke boots the server on a random port with a temporary SQLite file and checks, over real HTTP:
- signup without the setup token is refused, with it the first admin is created, a second signup is closed;
/api/whoamiis 401 anonymously and 200 with a freshly minted token;- it builds
mycli, runsmycli loginheadlessly, approves the printed code as the signed-in admin, then runswhoami,get /api/whoamiandlogout, and checks the API call fails after logout.
CI note: this module needs Go 1.26, so run it in a job that uses that toolchain, separate from the root module jobs that run on 1.25.
- Serve over HTTPS and set
BASE_URLto the https origin: the session cookie is thenSecure. - Put the database on local disk. One process owns the file; WAL mode and a busy timeout are set in the DSN.
- Call
store.SweepExpiredon a ticker to delete expired rows (see the SQLite storage guide). - Replace
UserAbilitiesinserver.gowith your own role model.