Skip to content

Repository files navigation

userauth

Composable user management and authentication for Go HTTP applications.

The library is a set of small building blocks — an identity service, a password service, per-request authenticators, multi-step login and registration engines, and optional credential services (TOTP, recovery codes, email/SMS codes, personal access tokens, server-side sessions). You construct only the pieces you need and wire them together yourself: what you never construct never creates a table.

The pieces

Layer Packages Role
Vocabulary root (userauth) Domain types (User), capability interfaces (UserGetter, …), errors — no logic
Per-request auth auth/cookieauth, basicauth, headerauth, tokenauth, chain Authenticate every request on its own (middleware)
Flows flow/login, register, emailchange, pat Multi-step engines that establish or change credentials
Services service/user, password, session, totp, recoverycodes, verificationcode, pat, secondfactor, throttle, cipher Each owns one policy and delegates persistence to its own store interface (GORM store/db and store/memory implementations ship with each)

Interfaces are small and defined at the consumer, so any piece can be replaced: bring your own user storage by implementing user.Store — or just userauth.UserGetter if all you need is login.

Quick start: password login with cookie sessions

The minimal useful setup is the identity service, the password service, and a cookie-session login flow. Two tables (user_models, user_groups), no other state:

db, _ := gorm.Open(sqlite.Open("users.db"), &gorm.Config{TranslateError: true})

// identity + passwords
userStore, _ := userdb.New(db) // service/user/store/db
users, _ := user.NewService(userStore, user.Opts{DefaultEnabled: true})
passwords, _ := password.NewService(password.Opts{Cost: 12, Rehash: users})
registrar := user.Registrar{Users: users, Password: passwords} // creates accounts from plaintext

// cookie sessions (stateless flavour: everything lives in the encrypted cookie)
cookies, _ := cookieauth.NewCookieStore(hashKey, blockKey)
sessions, _ := cookieauth.New(cookieauth.Cfg{Store: cookies})

// the login engine: verify a password, establish the session
flow := &login.Flow{
    Users:   users,
    Methods: []login.Method{login.PasswordMethod{Users: users, Password: passwords}},
    Policy:  login.RequireAny(login.Chain{login.MethodPassword}),
    Session: sessions,
}

Your login handler calls flow.Submit(...); protected routes use sessions.Middleware. A complete, runnable version of exactly this is demo/examples/login/password.go.

The full setup

For the whole feature set over one database — every store, the delete cascade, session revocation on password change, and a composed second-factor provider — copy demo/setup. It is the reference wiring: compiled, copyable, and its tests pin the guarantees (deleting a user purges every satellite table, a password change revokes sessions, the full setup costs exactly nine tables).

stores, err := setup.New(db, setup.Opts{Cost: 12, DefaultEnabled: true})
// stores.Users, stores.Passwords, stores.Registrar, stores.Sessions,
// stores.TOTP, stores.Recovery, stores.PATs, ..., stores.Provider

Use-cases

Every row links a working example in the demo; each example uses only the library's public API and can be copied into a real application.

I want… Use Demo example
Password form login flow/login + auth/cookieauth demo/examples/login/password.go
Passwordless email-code login service/verificationcode + flow/login demo/examples/login/email.go
Two-step password + TOTP login service/totp, login.TOTPMethod demo/examples/login/totp.go
Recovery codes (lost authenticator) service/recoverycodes, login.RecoveryMethod demo/examples/login/recovery.go
A JSON login API for a SPA flow/login/handlers demo/examples/login/api.go
HTTP Basic auth auth/basicauth demo/examples/auth/basic.go
Trusted-header auth behind a proxy (Authelia, mod_auth_mellon, …) auth/headerauth demo/examples/auth/header.go
API tokens (PATs), also in a browser+API mix service/pat + auth/tokenauth + auth/chain demo/examples/auth/token.go, chain.go
Self-registration (forms or JSON) flow/register (+ handlers) demo/examples/register
A profile page: password/email change, 2FA enrolment, sessions, tokens service/user, service/totp, service/session, flow/pat demo/examples/profile
Admin user management, first-run bootstrap service/user (List, Bootstrap) demo/examples/admin
Per-user choice of second factor compose secondfactor.Provider demo/setup

Sessions: two flavours

auth/cookieauth runs either stateless — the whole session lives in an encrypted cookie, nothing server-side, no way to revoke remotely — or against a registry (service/session): the cookie carries an opaque ID, the server stores the session, and you get list/revoke ("log out my other devices"), revocation on password change, and per-user session caps. Pass cookieauth.Cfg.Store for the first, cookieauth.Cfg.Registry for the second. The stateless flavour never imports the registry — consumers that don't use it don't pay for it.

Demo

go run ./demo   # then open http://localhost:8085

Every feature above is mounted with an index page describing it. See demo/README.md.

More documentation

Design decisions, package placement rules, and migration guides for breaking changes live in docs/agents/ — start with architecture.md.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages