First working application
Run the complete browser flow, then use the same configuration and wrapper in your backend.
First working application
The runnable examples/onboarding application uses SQLite, the real HTTP
handlers, host-only development cookies and terminal email delivery. Its browser
page completes signup, email verification, password login, email 2FA, a protected
application mutation and logout. It exposes no mailbox or code-reading endpoint.
Run from this checkout
These shell commands use a fresh local SQLite database. Generate the root secret once and keep it for subsequent restarts of this development database.
export DATABASE_URL='file:onboarding.db?_pragma=foreign_keys(1)&_pragma=busy_timeout(5000)'
export GOAUTH_SECRET="$(openssl rand -hex 32)"
go run ./cmd/goauth migrate --driver sqlite --dsn "$DATABASE_URL"
go run ./examples/onboardingOpen http://localhost:8080. Use that hostname consistently. The example
listens only on loopback; port 8080 must be available. Without GOAUTH_SECRET,
or before migration, startup fails with the relevant configuration/migration
error before workers start. Restarting does not migrate the database.
For PowerShell, generate a development secret with
$env:GOAUTH_SECRET = [Convert]::ToHexString([Security.Cryptography.RandomNumberGenerator]::GetBytes(32))
and set $env:DATABASE_URL to the same DSN. Run the same Go commands, replacing
"$DATABASE_URL" with "$env:DATABASE_URL".
From a consuming module pinned to v0.5.3, use the package paths selected by that module instead of the checkout-relative commands:
go get github.com/nazimdjebloun/go-auth/examples/onboarding@v0.5.3 github.com/nazimdjebloun/go-auth/cmd/goauth@v0.5.3
go run github.com/nazimdjebloun/go-auth/cmd/goauth migrate --driver sqlite --dsn "$DATABASE_URL"
go run github.com/nazimdjebloun/go-auth/examples/onboardingThe example's SQLite driver is included by the executable. Your own SQLite
backend must blank-import modernc.org/sqlite, as shown in its source. The CLI
and application must select the same library/catalog version.
Complete the browser flow
- Enter an email, name and password, then choose Create account. The page first obtains the mandatory CSRF token, then submits signup. The password follows the default policy: 8..128 Unicode code points with a letter and digit, and the default unpeppered bcrypt input bound of 72 bytes.
- Copy the eight-character verification code from the backend terminal into
Email code. The response has
step: "sign_in"; the page signs in using the credentials still held in memory. Email verification itself issues no session credentials. - Enter the new six-digit 2FA code from the terminal. Only successful second
factor verification creates session/refresh cookies. The page reloads
/auth/meafter theauthenticatedstep. - Choose Make protected request.
POST /app/hellousesAuth.Protectand returns the authenticated user ID. The client sends the current signed double-submit token; authentication changes replace that token. - Choose Sign out. Logout revokes the session, clears credentials and replaces CSRF protection. A later protected request requires sign-in.
Resend is available on the code screen. A page reload during signup verification discards the in-memory password; sign in again when needed. Existing sessions restricted by verification use the same screen and can resume after verifying their own account. No password, code or browser credential is written to local storage by this example.
The example explicitly opens public password registration and requires email
verification and email 2FA. These are example choices, not new library defaults.
It uses EnvironmentDev, including HTTP and a log mailer. Configure a real
mailer and HTTPS for a deployed application; see Deployment.
Use it in your backend
examples/onboarding/main.go contains the full configuration, explicit driver
import, route mounting and graceful shutdown. index.html contains the CSRF
bootstrap/replacement and step handling.
Copy the relevant parts into your application rather than building a separate
authentication implementation.
Use Auth.Protect("POST /your-route/{id}", handler) on your own authenticated
browser routes and put authorization wrappers inside it. Keep CORS outside a
method-selecting router so preflight runs before dispatch. Do not apply Protect
to the built-in public authentication routes. See
Protect application routes for authorization examples.
Closed installations and the first administrator
For an internal tool, keep AllowPublic: false in the application's
WithRegistration configuration. The library already defaults to closed signup;
the example opens it only to demonstrate registration. Seed the first verified
administrator after migration and before accepting users:
export ADMIN_EMAIL='admin@example.test'
go run ./cmd/goauth seed-admin --driver sqlite --dsn "$DATABASE_URL" --env devThe CLI prompts for a password or generates one if the prompt is left empty,
and checks development email delivery before writing the account. It does not
require opening signup. In your own application, log in that account through the
admin panel's dedicated admin login endpoint. With optional application roles,
add --app-permissions and configure/initialize that feature as described in
App roles and permissions.
What is tested
The example's test uses its actual handler, a real migrated SQLite database and
one HTTP cookie jar. It checks startup rejection before migration, the complete
flow above, rejection before login and 2FA, and CSRF rejection even with valid
session cookies. Run go test ./examples/onboarding from the checkout.